subclassing child window c++ - c++

I am working on windows and i chose the c++ as language. My application is a win32 application and I am not using MFC classes, but only the native API.
My main window contain a Tab control in which there is a Listview control. I tried to Subclass both the control, but it is not working even though i follow the msdn guide.
The function I used are:
SetWindowLong and GetWindowLong
so I changed the child's procedures but it seems the main window catches every messages that controls send ( through WM_NOTIFY ) and every WM messages. I thought that it may concern focus but I do not have any idea on how implement this kind of situation: a child control which is the parent of an another child control.
I have created the Tab control in this way.
code:
hwndTab = CreateWindow(WC_TABCONTROL, "",
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
0, 0, rcClient.right, rcClient.bottom,
winHandle, NULL, hInst, NULL);
OldUserTabProc = (WNDPROC)GetWindowLong(hwndTab, GWL_WNDPROC);
SetWindowLong(hwndTab, GWL_WNDPROC, (LONG_PTR)UserTabProc);
Here The Tab control procedure
LRESULT CALLBACK UserTabProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_LBUTTONDOWN:
break;
case WM_RBUTTONUP:
break;
case TCN_SELCHANGE:
{
userCurrentTab = TabCtrl_GetCurSel( userTab );
break;
}
case TCN_SELCHANGING:
{
break;
}
};
return CallWindowProc( OldUserTabProc, hWnd, message, wParam, lParam );
}
The listview has as parent the Tab control.

Values like TCN_SELCHANGE are not message types and they aren't sent to the control themselves. They are notifications (the N stands for "notification"). Notifications are sent by the control to the parent using a message like WM_NOTIFY or WM_COMMAND. You cannot intercept them by subclassing the control.
If you want to change the way the parent handles those notifications, you need to subclass the parent.

Related

C++ and Win32 WC_DIALOG close event problem

my English is bad. sorry
HWND DIALOG_0 = CreateWindowEx(0, WC_DIALOG, "Security Alert", DS_SETFONT | WS_OVERLAPPEDWINDOW | WS_VISIBLE, 600,300,300,200,Win.hwnd_0,NULL,NULL,NULL);
(WNDPROC)SetWindowLongPtr(DIALOG_0 , GWLP_WNDPROC, (INT_PTR)dede);
ShowWindow (DIALOG_0, SW_SHOW);
UpdateWindow(DIALOG_0);
How do I do the shut down event.
How do I make HWND click events
I use it, but it gets locked up.
(WNDPROC)SetWindowLongPtr(DIALOG_0 , GWLP_WNDPROC, (INT_PTR)dede);
WC_DIALOG create dede function
LONG_PTR __stdcall Win32::dede(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CTLCOLORDLG:
return (INT_PTR)GetStockObject(HOLLOW_BRUSH);
break;
default:
DefWindowProc(hDlg, message, wParam, lParam);
break;
}
return (INT_PTR)FALSE;
}
You usually create dialogs with DialogBox or CreateDialog, not with CreateWindow. If you use CreateWindow then you cannot use the DS_ styles.
GWLP_WNDPROC replaces the original window procedure and you normally should call CallWindowProc, not DefWindowProc. If you don't do this then you don't get the default IDCANCEL handling and all the other things a dialog usually provides.
Catch WM_CLOSE and WM_COMMAND to handle close and click events.
MSDN has a dialog guide here.

Where is the best place to create a child control of a child window in a pure WinAPI GUI App?

I am working on a WinAPI only application. I want to create a STATIC child window that will be used as a "container" to child controls. In the examples that I have found so far, the "container" window is created catching the WM_CREATE in the main window procedure. I assumed the best place to create the child controls of the child window was by catching the WM_CREATE for the child window. To do this, I first need to subclass the child window to point to the new window procedure. The thing is the window is created before it is subclassed, therefore the WM_CREATE is sent to the original procedure rather than to my user created procedure. I can of course create the child controls after creating the child static window inside the main window procedure, but I do not believe this to be the best way to do it. What is the best option?
Working sample code:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HWND hContainer = CreateWindow(WC_STATIC, L"Container", WS_CHILD, 0, 0, 100, 50, hWnd, (HMENU)ID_CONTAINER, NULL, NULL);
WNDPROC wpOldProc = (WNDPROC)SetWindowLongPtr(hContainer, GWLP_WNDPROC, (LONG_PTR)ChildWindowProc);
HWND hButton = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU)ID_BUTTON, NULL, NULL); // This works well
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK ChildWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
// HWND hButton = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU)ID_BUTTON, NULL, NULL);
// This point is never reached because the WM_CREATE message is sent before subclassing of the window
}
break;
default:
break;
}
return CallWindowProc(gsHdl.wpTE, hWnd, message, wParam, lParam);
}
The main principal here is separation of concerns: A window will typically create its children in response to its WM_CREATE message as:
This ensures the window "owns" the creation of its children. It also guarantees that when the parent window is created directly by classname, all the children get automatically created. And lastly, because WM_CREATE is sent before a window is made visible/painted, it ensures that the child windows are all created by the time the window is first painted.
A lot of these considerations fall away when using child windows to organise child windows :- If you are making a proper abstracted control window that is one thing, but if you are just arranging some relatively standard windows controls that you want the main window to be able to interact with then deep hierarchies are annoying to navigate, there are some weirdness in how mouse and painting happen where you might want to actually arrange the container and its children in the "wrong" z-order that you could not achieve if they were strictly arranged as child/parents.
Which is to say there is nothing wrong with creating a static window, and using the returned HWND as a parent window on subsequent lines - especially if that reduces the number of window classes, lines of code / creation convolution - and simplifies the parent windows relationship to its controls.
Creating sub-windows/controls under WM_CREATE messages does ensure that sub-windows/controls are created after successful window creation and that all sub-windows/sub-controls are automatically created when creating the main window.
But I don't think it's much different from the below:
HWND hContainer = CreateWindow (WC_STATIC, L "Container", WS_CHILD, 0, 0, 100, 50, hWnd, (HMENU) ID_CONTAINER, NULL, NULL);
if(hContainer)
{
HWND hButton = CreateWindow (WC_BUTTON, L "Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU) ID_BUTTON, NULL, NULL);
}
It also ensures the creation order and preconditions.
If you really need to modify WinProc and capture WM_CREATE messages in a standard windows controls, SetWindowsLongPtr does not meet your requirements. Use SetClassLongPtr before creating "Container" instead.

Add event handler to button in c++

I created a button in c++ as follows:
HWND btn = CreateWindow(
"BUTTON",
"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10,
10,
100,
100,
hWnd,
NULL,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
The button is displayed in the main window (hWnd) but I don't know how or where to give it an event handler. Any help please?
There are three ways to detect the button being clicked.
The preferred approach is to add a WM_COMMAND handler to the window procedure of the button's parent window. When the button is clicked, it sends a BN_CLICKED notification to its parent window. This is described in the MSDN documentation for buttons:
Handling Messages from a Button
Notification Messages from Buttons
If you are adding the button to a parent window that you do not own, you can subclass the parent window using SetWindowsLongPtr(GWL_WNDPROC) or SetWindowSubClass(), and then you can handle messages that are sent to it, such as BN_CLICKED. This only works if the subclassing code runs in the same thread that owns the parent window.
Alternatively, you can subclass the button itself and handle keyboard and mouse messages instead.
Another option is to set an event hook using SetWinEventHook() asking to receive EVENT_OBJECT_INVOKED events. In the event callback procedure, the provided hwnd, ID, and idChild parameters will identify the control that is being invoked, such as a clicked button.
When the button is clicked, it sends a BN_CLICKED notification message (carried by the WM_COMMAND message) to its parent window. The BN_CLICKED notification code is in the HIWORD of the wParam of the message. The LOWORD of the wParam of the message has the ID of the button. The lParam of the message has the HWND of the button. This is all in the online Windows docs. Google for BN_CLICKED.
Consider this pseudo code... it's from memory. Basically, add the stuff inside the WM_COMMAND case to the window procedure that you already have:
LRESULT WINAPI YourWindowProc(HWND hWnd, UINT nMsg, WPARAM wp, LPARAM lp)
{
switch (nMsg)
{
case WM_COMMAND:
{
switch (HIWORD(wp))
{
case BN_CLICKED:
{
switch (LOWORD(wp))
{
case IDC_BUTTON1: // or whatever the ID of your button is...
{
// do stuff for button...
break;
}
}
break;
}
}
break;
}
default:
return DefWindowProc(hWnd, nMsg, wp, lp);
}
return 0;
}
In the second-to-last parameter, type (HMENU)1
in the WNDPROC:
switch (uMsg)
{
case WM_COMMAND:
switch (wParam)
{
case 1:
// Code
}
}

Win32: C++: How do I re-focus on Parent Window after clicking in a child window?

In my Win32 CPP program, I have defined some Child Window to display various text strings using something like:
hnd_to_this_ch_window = CreateWindow(
L"EDIT",L"Some initial text", WS_VISIBLE | WS_CHILD | ES_LEFT,
position_of_this_window_X,
position_of_this_window_Y,
TEXTOUT_DEFAULT_WIDTH,
TEXTOUT_DEFAULT_HEIGHT,
handle_to_my_parent_window, NULL,
hinstance_variable_used_by_create_window,
NULL )
My problem is that if I click with my mouse to select the text in one of such child windows (to, say, copy it somewhere), the focus of the application goes to this child window and so any keypresses which used to be handled through my main windows CALLBACK (with case WM_KEYDOWN:) are now captured into the child window, where they appear as inputted characters. What magic function do I call to have the focus go back to the parent (so that my WM_KEYDOWN) can work again? I was hoping I could just click on the main Window's title bar and that would take it back to normal, but that isn't working (because, obviously, my program is lacking some extra logic).
Handle the WM_KILLFOCUS message in the window procedure of the window you want to focus, and restore the focus using the SetFocus function.
If you want to focus the window when it is clicked, handle the WM_LBUTTONDOWN message.
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// Restore the focus when it was lost.
if (Msg == WM_KILLFOCUS) {
SetFocus(hWnd);
// Msg was handled, return zero.
return 0;
}
// Or when the window is clicked.
if (Msg == WM_LBUTTONDOWN) {
SetFocus(hWnd);
// Msg was handled, return zero.
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
case WM_KEYDOWN:
SetFocus(Parent_Hwnd);
return SendMessage(Parent_Hwnd,WM_KEYDOWN,wParam,lParam);

Subclass existing window with Win32

I am currently trying to grab all of the user input to the windows calculator app. It seems the way to do this is to use Win32 to intercept all of the keyboard and mouse inputs that are intended for the calculator window. I have read the MSDN page on subclassing a window at the link below and have done some research on subclassing.
I have the syntax for subclassing a window, but I am not sure how to tell the program which window I am looking to subclass.
the code that I have so far is listed below. My problem right now is that I am not sure how the variable "hWndEdit" is assigned. I am pretty new to Win32 programming so any help is appreciated.
(link)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633570(v=vs.85).aspx
WNDPROC wpOrigEditProc;
wpOrigEditProc = (WNDPROC) SetWindowLong(hWndEdit,GWL_WNDPROC,(long) WndEditProc);
LRESULT CALLBACK WndEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CHAR:
case WM_KEYUP:
case WM_KEYDOWN:
if (hWnd == hWndEdit)
return 0;
break;
case WM_DESTROY:
// Remove the subclass from the edit control.
SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG) wpOrigEditProc);
break;
default:
return CallWindowProc((WNDPROC ) wpOrigEditProc, hWnd, message, wParam, lParam);
}
return CallWindowProc((WNDPROC ) wpOrigEditProc, hWnd, message, wParam, lParam);
}
To find a window, first use Spy++ (A tool that gets installed with Visual Studio) to find the class name and the window name of the calculator main window. Then, in your application, use the FindWindow API:
hWndEdit = FindWindow(className, windowName);
Although, I'm not sure that subclassing is the right method here since the Calculator window is not owned by your application. You should do this with hooks.