Click to See Complete Forum and Search --> : [RESOLVED] My Child Window (a splitter window) does not process mouse notification


Irwan
July 1st, 2010, 10:05 PM
Hi,



I'm having problem. I have reduce the code to simplify the question.

In this code, I have create 3 child windows (or I refered as panel) to the the parent window (hwnd) in Client Area.



The App Handle = hInstance

The Main/Parent Window = hwnd

The Child Window to hwnd = hwndMsgPanel, hwndLeftPanel, hwndSplitterPanel



The problem:

1. I try to process WM_MOUSEMOVE in WndProc (for hwnd).

2. Whenever Cursor is x>0 in client area, it should change to IDC_SIZEWE.

3. Because x>0 is mean all the client area, so the cursor should change IDC_SIZEWE whenever it in client.

4. But it is not in case of my app. The cursor only change when it is in client area but not ontop of all the child window area (area which is sepcify to hwndMsgPanel, hwndLeftPanel, hwndSplitterPanel).

5. I suspect that, WndProc (for hwnd) do not process the message send to its child window (because hwndMsgPanel, hwndLeftPanel, hwndSplitterPanel is the child window to hwnd).

6. I test process the WM_MOUSEMOVE in the one of the child window, let say LeftPanelProc (wndProc for hwndLeftWnd). Now the cursor change to IDC_SIZEWE whenever the cursor ontop the hwndLeftPanel area. (The code is not show below as this is not the question).

7. But I suppose the message send to hwnd, and hwnd should able to handle its child right?

8. Moreover, the code in http://www.win32apicode.com/splitter.php is able to do it.



Why my app hwnd can't process mouse in its child window?



Thanks, I think this question will be easy for the you guys, the master. :)





#include <windows.h> // For Win32 API





// API Function Prototype
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LeftPanelProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SplitterPanelProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MsgPanelProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);






int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
// Win32 API Structure Declaration
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
static TCHAR szAppName[] = TEXT("SplitterApp");
HBRUSH bgBrushA, bgBrushB, bgBrushC, bgBrushD;


// Main Window Class
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, szAppName);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = bgBrushA = CreateSolidBrush(RGB(195,218,249)); // This is same with FrameBase.BgColor Property
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = szAppName;
RegisterClass(&wndclass);


// Left Panel Class
wndclass.lpfnWndProc = LeftPanelProc;
wndclass.hbrBackground = bgBrushB = CreateSolidBrush(RGB(255,255,255)); // This is same with LeftPanel.BgColor Property
wndclass.lpszClassName = TEXT("LeftPanel");
RegisterClass(&wndclass);



// Splitter Panel Class (divider between Left Panel & Work Panel)
wndclass.lpfnWndProc = SplitterPanelProc;
wndclass.hbrBackground = bgBrushC = CreateSolidBrush(RGB(255,0,0)); // This is same with SplitterPanel.BgColor Property
wndclass.lpszClassName = TEXT("SplitterPanel");
RegisterClass(&wndclass);



// Msg Panel Class
wndclass.lpfnWndProc = MsgPanelProc;
wndclass.hbrBackground = bgBrushD = CreateSolidBrush(RGB(255,255,0)); // This is same with LeftPanel.BgColor Property
wndclass.lpszClassName = TEXT("MsgPanel");
RegisterClass(&wndclass);



// Create Window for Main Window
hwnd = CreateWindow( szAppName,
szAppName,
WS_OVERLAPPEDWINDOW | SW_MAXIMIZE | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
900,
500,
NULL,
NULL,
hInstance,
szCmdLine);



// Message Pump
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

// Delete All Brush created to paint all panel & window background
DeleteObject(bgBrushA);
DeleteObject(bgBrushB);
DeleteObject(bgBrushC);
DeleteObject(bgBrushD);

return (int)msg.wParam;
}





// Main Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hwndLeftPanel, hwndSplitterPanel, hwndMsgPanel;
static CREATESTRUCT *cs;
RECT rect;
static HCURSOR hcSizingWE;
int MouseXPos, MouseYPos;
bool mouseOverFlag;



switch(iMsg){
case WM_CREATE :
cs = (CREATESTRUCT *)lParam; // For Application Handle hInstance


// Create Left Panel
hwndLeftPanel = CreateWindowEx( 0,
TEXT("LeftPanel"),
TEXT("Left Panel"),
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
0, // Panel Coord. will be handle in the WM_SIZE via
0, // MoveWindow(). No InvalidateRec() in this case
0, // Panel Size will be handle in the WM_SIZE via
0, // MoveWindow(). No InvalidateRec() in this case
hwnd, // The Top Window Handle
0, // No menu for panel
cs->hInstance, // The App Handle
0);

// Create Splitter Panel
hwndSplitterPanel = CreateWindowEx( 0,
TEXT("SplitterPanel"),
TEXT("Splitter Panel"),
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
0, // Panel Coord. will be handle in the WM_SIZE via
0, // MoveWindow(). No InvalidateRec() in this case
0, // Panel Size will be handle in the WM_SIZE via
0, // MoveWindow(). No InvalidateRec() in this case
hwnd, // The Top Window Handle
0, // No menu for panel
cs->hInstance, // The App Handle
0);


// Create Msg Panel
hwndMsgPanel = CreateWindowEx( 0,
TEXT("MsgPanel"),
TEXT("Message Panel"),
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
0, // Panel Coord. will be handle in the WM_SIZE via
0, // MoveWindow(). No InvalidateRec() in this case
0, // Panel Size will be handle in the WM_SIZE via
0, // MoveWindow(). No InvalidateRec() in this case
hwnd, // The Top Window Handle
0, // No menu for panel
cs->hInstance, // The App Handle
0);

InvalidateRect(hwnd, &rect, TRUE);

break;




case WM_SIZE :

GetClientRect(hwnd, &rect);

// Set Panels Size and Position for first time
// To make sense on the numbering I use, following is the definition
// MsgPanel Height = 30
// LeftPanel Width = 250
// SplitterPanel Width = 500
MoveWindow(hwndMsgPanel, rect.left, rect.top, rect.right, 30, FALSE);
MoveWindow(hwndLeftPanel, rect.left, rect.top + 30, 250, rect.bottom-30, FALSE);
MoveWindow(hwndSplitterPanel, rect.left + 250, rect.top + 30, 50, rect.bottom-30, FALSE);

// Load App used Cursor
hcSizingWE = LoadCursor(NULL, IDC_SIZEWE);

InvalidateRect(hwnd, &rect, TRUE);

break;




case WM_MOUSEMOVE:
// The Test Flag
mouseOverFlag = 0;


// Convert Cursor Position from LPARAM
MouseXPos = (int) LOWORD(lParam);
MouseYPos = (int) HIWORD(lParam);

if (MouseXPos > 0 && GetCursor() != hcSizingWE)
SetCursor(hcSizingWE);

break;




case WM_CLOSE :
DestroyWindow(hwnd);

break;




case WM_DESTROY :
PostQuitMessage(0);

break;
}

return DefWindowProc(hwnd, iMsg, wParam, lParam);
}






LRESULT CALLBACK LeftPanelProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch(iMsg)
{
case WM_CREATE :
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}





LRESULT CALLBACK SplitterPanelProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch(iMsg)
{
case WM_CREATE :
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}





LRESULT CALLBACK MsgPanelProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch(iMsg)
{
case WM_CREATE :
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

Irwan
July 2nd, 2010, 08:38 AM
It has been 3 days stuck on this one. Can't anybody help me?

hypheni
July 2nd, 2010, 11:36 AM
Did you check for the return value of MoveWindow and if its failed check for the GetLastError.

Irwan
July 3rd, 2010, 02:22 AM
NO. i get it wrong.

in http://www.win32apicode.com/splitter.php, they able to capture mouse movement by hwnd (top most window) using WndProc because the splitter bar is part of hwnd. Its look like it a child window (by graphic illusion) but is is actually a hwnd window, area which is not cover by other child window. That why WndPRod for hwnd is able to process the Mouse move.


Pardon me

hypheni
July 3rd, 2010, 05:47 AM
Leave the other part and tell if you checked for the return value. If you get an 0 then check for GetLastError and tell whats the output ?

Igor Vartanov
July 5th, 2010, 08:35 AM
There's no need to pass mouse move to parent/main window, as the splitter window itself is able to handle all the stuff alright.

The sample goes.

Irwan
July 5th, 2010, 07:01 PM
Yes Mate.

I guess so. I need to process it in the SplitterPanelProc.

I miss read coding in the example.