When using SetWindowLong() to subclass an edit control, I have found various documentation
that states the address of the original window procedure should be reset at application
close out during the WM_CLOSE or WM_DESTROY message. On the other hand, I learned Sdk style
Windows programming mostly from Charles Petzold's books, and in his only examples of
subclassing in his Colors program he does not do this. This is true in his Windows 95 book
and in his Windows 98 book. So I've never done it either the many times I've done this, and
to the best of my knowledge with no ill effects.
Kyle Marsh from Microsoft states this in his article "Safe Subclassing In Win32"
The application also needs the original window procedure address for removing the subclass from the window. The application removes the subclass from the window by calling SetWindowLong again. The application passes the address of the original window procedure with the GWL_WNDPROC option and the handle to the window being subclassed.
Can anyone shed some light on this for me? Petzold couldn't possibly be wrong could he?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
IMHO that's right. AFAIK that is the canonical (and now disappearing) form to do the thing. More or les exactly what I do. The only difference is that I omit the
Thanks for the reply Old Newbie. If I understand you right you see it pretty much the way I do. Below is a specific example using Sdk style. All I did was create a simple window, add a text box to the middle of it, then use SetWindowLong() in the WM_CREATE message to subclass it like so...
When using SetWindowLong() to subclass an edit control, I have found various documentation
that states the address of the original window procedure should be reset at application
close out during the WM_CLOSE or WM_DESTROY message. On the other hand, I learned Sdk style
Windows programming mostly from Charles Petzold's books, and in his only examples of
subclassing in his Colors program he does not do this. This is true in his Windows 95 book
and in his Windows 98 book. So I've never done it either the many times I've done this, and
to the best of my knowledge with no ill effects.
Kyle Marsh from Microsoft states this in his article "Safe Subclassing In Win32"
The application also needs the original window procedure address for removing the subclass from the window. The application removes the subclass from the window by calling SetWindowLong again. The application passes the address of the original window procedure with the GWL_WNDPROC option and the handle to the window being subclassed.
Can anyone shed some light on this for me? Petzold couldn't possibly be wrong could he?
IMHO that's right. AFAIK that is the canonical (and now disappearing) form to do the thing. More or les exactly what I do. The only difference is that I omit the
SetWindowLong (GetDlgItem(hwnd,IDC_TEXTBOX), GWL_WNDPROC, (DWORD)fnOldEdit);
sentence int the VM_CLOSE case clause.
Old Newbie.
AFAIK there are not necessity to restore the original window proc when you close the application. I never do that without known "ill effects".
I never had read that necessity in other books.
Old Newbie.
Thanks for the reply Old Newbie. If I understand you right you see it pretty much the way I do. Below is a specific example using Sdk style. All I did was create a simple window, add a text box to the middle of it, then use SetWindowLong() in the WM_CREATE message to subclass it like so...
fnOldEdit=(WNDPROC)SetWindowLong(hTextBox,GWL_WNDPROC,(LONG)EditProc);
then in the WM_CLOSE message...
SetWindowLong(GetDlgItem(hwnd,IDC_TEXTBOX),GWL_WNDPROC,(DWORD)fnOldEdit);
Below is the full program, but I really see no need to do this at all???
(shure wish code would format here)
//
include <windows.h>
define IDC_TEXTBOX 1200
WNDPROC fnOldEdit;
//
LRESULT CALLBACK EditProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
return CallWindowProc(fnOldEdit, hwnd, iMsg, wParam, lParam);
}
//
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HINSTANCE hIns;
HWND hTextBox;
int iStyle;
switch (message)
{
case WM_CREATE:
hIns=((LPCREATESTRUCT)lParam)->hInstance;
iStyle=WS_CHILD | WS_VISIBLE | WS_BORDER;
hTextBox=CreateWindow("edit",0,iStyle,90,60,50,25,hwnd,(HMENU)(IDC_TEXTBOX),hIns,0);
fnOldEdit=(WNDPROC)SetWindowLong(hTextBox,GWL_WNDPROC,(LONG)EditProc);
return 0;
case WM_CLOSE:
SetWindowLong(GetDlgItem(hwnd,IDC_TEXTBOX),GWL_WNDPROC,(DWORD)fnOldEdit);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPrev,LPSTR lpszArg,int iShow)
{
WNDCLASSEX wincl;
MSG messages;
HWND hWnd;
wincl.hInstance = hIns;
wincl.lpszClassName = "Form1";
wincl.lpfnWndProc = WndProc;
wincl.style = CS_HREDRAW | CS_VREDRAW;
wincl.cbSize = sizeof(WNDCLASSEX);
wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
RegisterClassEx(&wincl);
hWnd=CreateWindow("Form1","Form1",WS_OVERLAPPEDWINDOW,150,200,250,200,0,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}