Jump to content
  • Advertisement
Sign in to follow this  
hplus0603

Win32 child windows not getting mouse clicks

This topic is 4426 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm writing a plug-in for another application. In my plug-in, I can create a settings window, when handed a parent window HWND. What I do is create an "empty" window (WS_CHILD style) to sit inside the parent HWND, and then create my controls (a ListView and a Button) inside this empty window. So far so good; this works. However, I can't get mouse clicking to dispatch to the controls. Clicking the windows does nothing. Keyboard input works; I can keyboard navigate and activate the button with spacebar (and scroll the list view); I just can't click. So, what's causing the mouse messages to not get to the children? The sad thing is that I recall having had this problem a few years back, but I'm drawing a blank on what the cause was at the time. Googling doesn't work, because all the words I can think of are too common. Here's some code; the host is setting up the parent window:
	t.style = WS_POPUPWINDOW|WS_DLGFRAME|DS_MODALFRAME|DS_CENTER;
	t.cx = 100;
	t.cy = 100;
	DialogBoxIndirectParam (GetModuleHandle (0), &t, 0, (DLGPROC)EditorProc, (LPARAM)plugin);


INT_PTR CALLBACK EditorProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_INITDIALOG :
		{
			SetWindowText (hwnd, "The Title");
			SetTimer (hwnd, 1, 20, 0);

			if(plugin)
			{
				plugin->dispatcheropen(hwnd);
				ERect* eRect = 0;
				effect->getRect(&eRect);
				if(eRect)
				{
					int width = eRect->right - eRect->left;
					int height = eRect->bottom - eRect->top;
					if(width < 100)
						width = 100;
					if(height < 100)
						height = 100;

					RECT wRect;
					SetRect (&wRect, 0, 0, width, height);
					AdjustWindowRectEx (&wRect, GetWindowLong (hwnd, GWL_STYLE), FALSE, GetWindowLong (hwnd, GWL_EXSTYLE));
					width = wRect.right - wRect.left;
					height = wRect.bottom - wRect.top;

					SetWindowPos (hwnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE);
				}
			}
		}
		break;

// removed CLOSE and TIMER handlers...

	}

	return 0;
}

Here is how my plug-in handles the open() call:

// this is slightly paraphrased, as there's really a wrapper class involved

bool Editor::open(void *ptr)
{
  PluginBase::open(ptr);
  //  ptr is a HWND
  window_ = ::CreateWindowEx(
    WS_EX_LEFT | WS_EX_CONTROLPARENT,
    myClass_,
    "Editor",
    WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
    0,
    0,
    500,
    300,
    (HWND)ptr,
    0,
    hInstance,
    someWrapper_);

  // listView styles are WS_VISIBLE | WS_CHILD | LVS_REPORT | LVS_NOSORTHEADER | 
  //    LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_TABSTOP;
  // listView exStyles are WS_EX_LEFT | WS_EX_ACCEPTFILES;
  listView_ = ... wrapper function ...
  listView_->enableExtendedStyles(LVS_EX_FULLROWSELECT | LVS_EX_FLATSB | 
      LVS_EX_TWOCLICKACTIVATE | LVS_EX_DOUBLEBUFFER | LVS_EX_GRIDLINES);
  listView_->addColumn("A", 40); // wrappers for ListView_InsertColumn()
  listView_->addColumn("B", 40);
  listView_->addColumn("C", 40);
  listView_->addColumn("D", 40);
  listView_->addColumn("File", 400);

  for (int i = 0; i < 128; ++i) {
    listView_->addRow(i);  // wrapper for ListView_InsertRow()
  }

  button_ = ::CreateWindowEx(
    WS_EX_LEFT,
    WC_BUTTON,
    "Push Me!",
    WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_CENTER | WS_TABSTOP,
    10,
    270,
    100,
    25,
    window_,
    0,
    hInstance,
    0);

  HCURSOR hc = (HCURSOR)::LoadImage(0, (LPCTSTR)OCR_NORMAL, IMAGE_CURSOR, 0, 0, LR_SHARED);
  ::SetCursor(hc);
  return true;
}


Window class registration for the top window is:
  // registering class on load-up
  INITCOMMONCONTROLSEX iccex;
  memset(&iccex, 0, sizeof(iccex));
  iccex.dwSize = sizeof(iccex);
  iccex.dwICC = ICC_BAR_CLASSES | ICC_LINK_CLASS | ICC_STANDARD_CLASSES | 
      ICC_USEREX_CLASSES | ICC_LISTVIEW_CLASSES;
  ::InitCommonControlsEx(&iccex);
  WNDCLASSEX wcex;
  memset(&wcex, 0, sizeof(wcex));
  wcex.cbSize = sizeof(wcex);
  wcex.style = CS_DROPSHADOW | CS_OWNDC;
  wcex.lpfnWndProc = &Win32Window::wndProc;
  wcex.cbClsExtra = 0;
  wcex.cbWndExtra = 0;
  wcex.hInstance = (HINSTANCE)hInstance;
  wcex.hIcon = 0;
  wcex.hCursor = (HCURSOR)::LoadImage(0, (LPCTSTR)OCR_NORMAL, IMAGE_CURSOR, 0, 0, LR_SHARED);
  wcex.hbrBackground = (HBRUSH)::GetStockObject(COLOR_BACKGROUND+1);
  wcex.lpszMenuName = 0;
  wcex.lpszClassName = "jwSP-class";
  wcex.hIconSm = 0;
  myClass_ = ::RegisterClassEx(&wcex);


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  LONG_PTR lp = ::GetWindowLongPtr(hWnd, GWL_USERDATA);
  if (!lp && msg == WM_NCCREATE) {
    lp = reinterpret_cast<LONG_PTR>(((CREATESTRUCT const *)lParam)->lpCreateParams);
  }
  Win32Window * wp = reinterpret_cast<Win32Window *>(lp);
  LRESULT ret = 0;
  if (wp != NULL) {
    if (msg == WM_NCCREATE) {
      wp->window_->setWindow(wp);
    }
    bool x = wp->window_->wndProc(msg, wParam, lParam, &ret);
    if (msg == WM_DESTROY) {
      wp->destroyed_ = true;
      if (!wp->deleted_) {
        delete wp;
      }
    }
    //  Warning! Window may have been deleted at this point!
    if (x) {
      // the wrapper wndProc just returns false, so this path is never taken
      // (confirmed with a breakpoint)
      return ret;
    }
  }
  //  Warning! Window may have been deleted at this point!
  return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
first thing i would do is check Spy++ to see who is getting the messages. check the button or the listview first and try clicking, see what happens. if nothing, try the child containter. if nothing, try the dialog parent. if the dialog parent is getting all the mouse messages, call GetCapture too see if the dialog has the capture. if it does, you might have a stray SetCapture somewhere. also, check to make sure the child container isn't disabled, that would cause the parent to receive all mouse messages as well.
Y-Go

Share this post


Link to post
Share on other sites
Thanks for the suggestions. I've already checked that there is no stray capture, and I've already checked that the windows are not disabled (in fact, I added a superfluous EnableWindow() when creating the window), but I'll check with Spy++ what happens to the messages.

Share this post


Link to post
Share on other sites
Nothing like waking up fresh in the morning to fix a problem. I had set the parent of the child windows to the wrong window (the top level window) so the "container" window was on top of the children and catching all the messages. Stupid bug, like all bugs once you find them :-) Thanks for the Spy++ suggestion, btw.

Share this post


Link to post
Share on other sites
hplus0603,

Is the button and listview children to the window titled "EDITOR"? If it is, I would suggest making just a "STATIC" with the WS_GROUP style, I've found those to be better containers. Also, is this your own homebrew window library?

-brad

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!