What values are you receiving for msg? Don't forgot this is a static control and not a 'normal' window.
Printable View
When you subclass a control, you don't receive the WM_CREATE messages etc as these have already been sent before you change the wndproc routine. If you want to receive the WM_CREATE etc mesages for controls you will need to superclass the control (as opposed to subclass that you do now).
For details see
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
almost done.. the WM_CREATE is used:
but i continue with 2 problems:Code:#include <windows.h>
#include <iostream>
#include <string>
#include <process.h>
using namespace std;
WNDPROC m_pfnPrevWndProc;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
SetWindowText(hwnd,"hello world");
break;
case WM_KEYDOWN:
SetWindowText(hwnd,"mouse move");
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return CallWindowProc(m_pfnPrevWndProc,hwnd, msg, wParam, lParam);
}
return 0;
}
class label
{
private:
HWND hwnd;
WNDCLASS wc;
public:
label(HWND value)
{
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo((HINSTANCE)GetModuleHandle(NULL), "STATIC", &wc);
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
m_pfnPrevWndProc = wc.lpfnWndProc;
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
RegisterClass(&wc);
hwnd = CreateWindowEx(
WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
"CSTATIC",
"",
SS_LEFT|WS_CHILD|WS_VISIBLE,
0, 0, 100, 100,
value,
NULL,
GetModuleHandle(NULL),
NULL);
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
}
COORD GetSize()
{
RECT LabelSize;
GetWindowRect(hwnd,&LabelSize);
COORD crdSize={LabelSize.right-LabelSize.left,LabelSize.bottom-LabelSize.top};
return crdSize;
}
void SetText(string text)
{
char* chrText=(char*)text.c_str();
SetWindowText(hwnd, chrText);
}
};
1 - seems the code isn't completed, because the others messages aren't used;
2 - how can i put the window procedure inside of the class?
if i put it in 'static', i can't use the m_pfnPrevWndProc variable, unless is static too :(
can you tell me something about put the procedure inside of the class?
heres where i found it: http://cboard.cprogramming.com/windo...dow-class.html
maybe now i can do it ;)
but tell me more about what isn't right, please.
To put the window procedure inside the class, it has to be static. As you say, you then can't access m_pfnPrevWndProc inside of the static procedure. One way round this is to store the value with the window using SetWindowLongPtr and GWLP_USERDATA. This way, the static class function can retrieve the value from the hwnd passed to wndproc using GetWindowLongPtr with GWLP_USERDATA. Note this isn't a good idea for controls (do it with their parent) so don't do this for the actual control itself as it may be using this data for other things. The other way of associating data with a window is to use windows properties. Use GetProp() and SetProp(). See http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx and http://msdn.microsoft.com/en-us/libr...eving_property.
One of the better books on this topic is
Windows 95 - A developers guide by Jeffrey Richter.
I know its quite an old book but this sort of windows detail hasn't changed much over the years (SetWindowLongPtr instead of SetWindowLong etc).
http://www.amazon.co.uk/Windows-95-D...velopers+guide
Note that later books by the same author (Advanced Windows, Programming Applications etc) don't cover these topics.
You may find this code snippet useful to have a look at.
Code://New wnd proc for edit control in value control
LRESULT CALLBACK NewEdit(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
HWND hanc = GetAncestor(hwnd, GA_ROOT);
PLSGM lsgm = (PLSGM)GetWindowLong(hanc, WEX_LS);
UINT id = GetWindowLong(GetParent(hwnd), GWL_ID) - STID;
//Check for special char tab, CR, shift tab use WM_KEYDOWN so can check for VK_SHIFT
if (message == WM_KEYDOWN) {
//If tab or CR then process as tab/CR from main control and move to other control
if ((wparam == VK_TAB) || (wparam == VK_RETURN)) {
if (wparam == VK_TAB) {
if ((USHORT)GetKeyState(VK_SHIFT) > 1) {
wparam = VK_BACK;
}
}
//Set lv text and close edit control
SetLVtext(lsgm);
//Process tab/CR
//CR now just closes and updates edit control
if (wparam != VK_RETURN) {
doTabCR(hanc, id + 1, wparam);
}
return (0);
}
}
if (message == WM_CHAR) {
//Ignore tab/CR as processed using WM_KEYDOWN
if ((wparam == TAB) || (wparam == CR)) {
return (0);
} else {
//If have ESC then close edit window but don't save contents
if (wparam == ESC) {
//Indicate edit control contents not changed
lsgm->lvdef.chg = FALSE;
DestroyWindow(hwnd);
return (0);
} else {
//Indicate contents changed
lsgm->lvdef.chg = TRUE;
}
}
}
//If edit control loose focus, save contents and close edit window
if (message == WM_KILLFOCUS) {
SetLVtext(lsgm);
return (0);
}
//Process message as normal
return (CallWindowProc(lsgm->lvdef.old, hwnd, message, wparam, lparam));
}
so what isn't right?
(even the control isn't showed)Code:static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc =(WNDPROC)SetWindowLongPtr (GetParent(hwnd),GWLP_USERDATA,NULL);
UINT i=(UINT)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
switch(msg)
{
case WM_CREATE:
{
SetWindowText(hwnd,"hello world");
break;
}
case WM_MOUSEMOVE:
{
SetWindowText(hwnd,"mouse move");
break;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (CallWindowProc(oldproc, hwnd, msg, wParam, lParam));
}
return 0;
}
SetWindowLongPtr goes in the class function that creates the control - and not in wndproc.Code:WNDPROC oldproc =(WNDPROC)SetWindowLongPtr (GetParent(hwnd),GWLP_USERDATA,NULL);
becomesCode:UINT i=(UINT)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
When you create the control, useCode:WNDPROC oldproc =(WNDPROC)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
But as I mentioned in my post #22, its better to use windows properties.Code:SetWindowLongPtr (GetParent(hwnd),GWLP_USERDATA,m_pfnPrevWndProc);
i think that i did what you said:
but the control isn't showed :(Code:#include <windows.h>
#include <iostream>
#include <string>
#include <process.h>
using namespace std;
class label
{
private:
HWND hwnd;
WNDCLASS wc;
WNDPROC m_pfnPrevWndProc;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc =(WNDPROC)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
UINT i=(UINT)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
switch(msg)
{
case WM_CREATE:
{
SetWindowText(hwnd,"hello world");
break;
}
case WM_MOUSEMOVE:
{
SetWindowText(hwnd,"mouse move");
break;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (CallWindowProc(oldproc, hwnd, msg, wParam, lParam));
}
return 0;
}
public:
label(HWND value)
{
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo((HINSTANCE)GetModuleHandle(NULL), "STATIC", &wc);
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
m_pfnPrevWndProc = wc.lpfnWndProc;
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
RegisterClass(&wc);
hwnd = CreateWindowEx(
WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
"CSTATIC",
"",
SS_LEFT|WS_CHILD|WS_VISIBLE,
0, 0, 100, 100,
value,
NULL,
GetModuleHandle(NULL),
NULL);
SetWindowLongPtr (GetParent(hwnd),GWLP_USERDATA,(LONG_PTR)m_pfnPrevWndProc);
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
}
COORD GetSize()
{
RECT LabelSize;
GetWindowRect(hwnd,&LabelSize);
COORD crdSize={LabelSize.right-LabelSize.left,LabelSize.bottom-LabelSize.top};
return crdSize;
}
void SetText(string text)
{
char* chrText=(char*)text.c_str();
SetWindowText(hwnd, chrText);
}
};
After the CreateWindowEx call, what is the value of hwnd? You don't check anywhere for errors. When you call an API function, you should always check that an error has not occurred.
yes.. you have right:
seems the control isn't created... and i don't know why :(Code:ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo((HINSTANCE)GetModuleHandle(NULL), "STATIC", &wc);
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
m_pfnPrevWndProc = wc.lpfnWndProc;
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
if (!RegisterClass(&wc)) MessageBox(NULL,"error","error",MB_OK); //the message isn't showed, so i think it's ok
hwnd = CreateWindowEx(
WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
"CSTATIC",
"",
SS_LEFT|WS_CHILD|WS_VISIBLE,
0, 0, 100, 100,
value,
NULL,
GetModuleHandle(NULL),
NULL);
if(hwnd==NULL) MessageBox(NULL,"error","error",MB_OK);//the message is showed, so i think isn't ok
SetWindowLongPtr (GetParent(hwnd),GWLP_USERDATA,(LONG_PTR)m_pfnPrevWndProc);
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
}
after more search the control is showed:
but the window procedure isn't correctly... i did something wrong on it but i don't know... please help me more for i learn moreCode:#include <windows.h>
#include <iostream>
#include <string>
#include <process.h>
using namespace std;
class label
{
private:
HWND hwnd;
WNDCLASS wc;
WNDPROC m_pfnPrevWndProc;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc =(WNDPROC)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
UINT i=(UINT)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
switch(msg)
{
case WM_NCCREATE: //works, because the control is showed
{
CREATESTRUCT *createstruct = (CREATESTRUCT*)lParam;
SetWindowLong(hwnd, GWL_USERDATA, (long)createstruct->lpCreateParams);
}
break;
case WM_CREATE:
{
SetWindowText(hwnd,"hello world");
break;
}
case WM_MOUSEMOVE:
{
SetWindowText(hwnd,"mouse move");
break;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (CallWindowProc(oldproc, hwnd, msg, wParam, lParam));
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
label(HWND value)
{
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo((HINSTANCE)GetModuleHandle(NULL), "STATIC", &wc);
wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
m_pfnPrevWndProc = wc.lpfnWndProc;
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
if (!RegisterClass(&wc)) MessageBox(NULL,"error","error",MB_OK);
hwnd = CreateWindowEx(
WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
"CSTATIC",
"hello",
SS_LEFT|WS_CHILD|WS_VISIBLE,
0, 0, 100, 100,
value,
NULL,
GetModuleHandle(NULL),
NULL);
if(hwnd==NULL) MessageBox(NULL,"error","error",MB_OK);
SetWindowLongPtr (GetParent(hwnd),GWLP_USERDATA,(LONG_PTR)m_pfnPrevWndProc);
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
}
COORD GetSize()
{
RECT LabelSize;
GetWindowRect(hwnd,&LabelSize);
COORD crdSize={LabelSize.right-LabelSize.left,LabelSize.bottom-LabelSize.top};
return crdSize;
}
void SetText(string text)
{
char* chrText=(char*)text.c_str();
SetWindowText(hwnd, chrText);
}
};
If hwnd is NULL, the reason for the error is obtained from GetLastError()
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
The error codes are explained here
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx