-
December 28th, 2013, 04:31 PM
#31
Re: [win32] - creating controls using class's
Originally Posted by Cambalinho
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 more
Where is the message pump?
Regards,
Paul McKenzie
-
December 28th, 2013, 04:34 PM
#32
Re: [win32] - creating controls using class's
Originally Posted by Paul McKenzie
Where is the message pump?
Regards,
Paul McKenzie
the CreateWindowEx() works with window procedure, if the window procedure isn't correct, so the control isn't created:
Code:
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:
{
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);
}
but maybe i did something wrong with it
-
December 28th, 2013, 05:50 PM
#33
Re: [win32] - creating controls using class's
When you process the WM_NCCREATE and WM_CREATE messages, you break out of the switch and then call DefWindowProc. You only call CallWindowProc if you don't handle the message in your WndProc routine. Unless you have a very good reason not too, you should always call CallWindowProc and not DefWindowProc for sub/super classing. In this case, the control isn't getting the WM_ messages it expects.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
December 28th, 2013, 06:15 PM
#34
Re: [win32] - creating controls using class's
Originally Posted by 2kaud
When you process the WM_NCCREATE and WM_CREATE messages, you break out of the switch and then call DefWindowProc. You only call CallWindowProc if you don't handle the message in your WndProc routine. Unless you have a very good reason not too, you should always call CallWindowProc and not DefWindowProc for sub/super classing. In this case, the control isn't getting the WM_ messages it expects.
i did:
Code:
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:
{
CREATESTRUCT *createstruct = (CREATESTRUCT*)lParam;
SetWindowLong(hwnd, GWL_USERDATA, (long)createstruct->lpCreateParams);
}
break;
case WM_CREATE:
{
CREATESTRUCT *createstruct = (CREATESTRUCT*)lParam;
SetWindowLong(hwnd, GWL_USERDATA, (long)createstruct->lpCreateParams);
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 CallWindowProc(oldproc, GetParent(hwnd), msg, wParam, lParam);
}
but the control isn't created.. the CreateWindowEx() give me error
the last error, give me '0'.
-
December 29th, 2013, 05:34 AM
#35
Re: [win32] - creating controls using class's
Code:
return CallWindowProc(oldproc, GetParent(hwnd), msg, wParam, lParam);
Why Getparent()? Why not just hwnd?
Also, why are you setting GWL_USERDATA in WM_CREATE and WM_NCCREATE?
If you post a complete program that compiles, I'll have a look at it.
Last edited by 2kaud; December 29th, 2013 at 05:36 AM.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
December 29th, 2013, 06:42 AM
#36
Re: [win32] - creating controls using class's
Originally Posted by 2kaud
Code:
return CallWindowProc(oldproc, GetParent(hwnd), msg, wParam, lParam);
Why Getparent()? Why not just hwnd?
Also, why are you setting GWL_USERDATA in WM_CREATE and WM_NCCREATE?
If you post a complete program that compiles, I'll have a look at it.
label.h:
(in window procedure i will need put some variables(like the events)... but i realy need avoid the static... anotherthing: if the window procedure is static, will be the same for all instances?(will be a problem?)
Code:
#include <windows.h>
#include <iostream>
#include <string>
#include <process.h>
using namespace std;
HWND hwnd;
HHOOK _hook;
WNDPROC previous_boring_subclassed_edit_proc;
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:
{
CREATESTRUCT *createstruct = (CREATESTRUCT*)lParam;
SetWindowLong(hwnd, GWL_USERDATA, (long)createstruct->lpCreateParams);
}
break;
case WM_CREATE:
SetWindowText(hwnd,"hello");
break;
case WM_MOUSEMOVE:
SetWindowText(hwnd,"hello");
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return CallWindowProc(previous_boring_subclassed_edit_proc, hwnd, msg, wParam, lParam);
}
//return 0;
}
class label
{
private:
public:
label(HWND value)
{
hwnd = CreateWindowEx(
WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
"STATIC",
"",
SS_LEFT|WS_CHILD|WS_VISIBLE,
0, 0, 100, 100,
value,
NULL,
GetModuleHandle(NULL),
NULL);
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
previous_boring_subclassed_edit_proc = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);//get the default procedure
SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR)WndProc);//set your custom procedure :)
}
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);
}
};
main.cpp:
Code:
#include <windows.h>
#include "Label.h"
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "CodeBlocksWindowsApp";
//creating the window
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
{
//create my label
label label1(hwnd);
label1.SetText("oi");
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
i'm sorry, but i'm trying
-
December 29th, 2013, 07:35 AM
#37
Re: [win32] - creating controls using class's
Originally Posted by Cambalinho
main.cpp:
Code:
#include <windows.h>
#include "Label.h"
....
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
{
//create my label
label label1(hwnd);
label1.SetText("oi");
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
i'm sorry, but i'm trying
Your label instance exists only within case WM_CREATE block. Then it goes out of scope and destroyed.
Victor Nijegorodov
-
December 29th, 2013, 07:42 AM
#38
Re: [win32] - creating controls using class's
Originally Posted by VictorN
Your label instance exists only within case WM_CREATE block. Then it goes out of scope and destroyed.
you have right.. thanks for that.. i change that
-
December 29th, 2013, 09:32 AM
#39
Re: [win32] - creating controls using class's
Try this. It will create the label and will write to file debug.txt the message numbers received. The file winuser.h details what they mean. It uses windows properites to store the old proc detail.
Code:
#include <windows.h>
#include <fstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
static char propname[] = "Cambalinho";
static char debugname[] = "debug.txt";
class label
{
private:
HWND hwnd;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ofstream os(debugname, ios_base::app);
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), propname);
if (oldproc == NULL)
MessageBox(NULL, "null", "null", MB_OK);
switch(msg) {
case WM_CREATE:
//This doesn't work as the window hasn't been created!
SetWindowText(hwnd, "hello world");
break;
default:
os << "0x" << hex << setw(4) << setfill('0') << msg << endl;
break;
}
//If oldproc is NULL then use DefWindowProc - but shouldn't be!
return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
label(HWND parent) {
WNDCLASS wc;
HINSTANCE mod = (HINSTANCE)GetModuleHandle(NULL);
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo(mod, "STATIC", &wc);
wc.hInstance = mod;
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
SetProp(parent, propname, (HANDLE)wc.lpfnWndProc);
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
if (!RegisterClass(&wc))
MessageBox(NULL, "error in register", "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,
parent,
NULL,
mod,
NULL);
if (hwnd == NULL)
MessageBox(NULL, "error in create", "error", MB_OK);
}
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);
}
};
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[] = "CodeBlocksWindowsApp";
//creating the window
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
DeleteFile(debugname);
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);
UpdateWindow(hwnd);
label label1(hwnd);
label1.SetText("oi");
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
December 29th, 2013, 09:44 AM
#40
Re: [win32] - creating controls using class's
Originally Posted by 2kaud
Try this. It will create the label and will write to file debug.txt the message numbers received. The file winuser.h details what they mean. It uses windows properites to store the old proc detail.
Code:
#include <windows.h>
#include <fstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
static char propname[] = "Cambalinho";
static char debugname[] = "debug.txt";
class label
{
private:
HWND hwnd;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ofstream os(debugname, ios_base::app);
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), propname);
if (oldproc == NULL)
MessageBox(NULL, "null", "null", MB_OK);
switch(msg) {
case WM_CREATE:
//This doesn't work as the window hasn't been created!
SetWindowText(hwnd, "hello world");
break;
default:
os << "0x" << hex << setw(4) << setfill('0') << msg << endl;
break;
}
//If oldproc is NULL then use DefWindowProc - but shouldn't be!
return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
label(HWND parent) {
WNDCLASS wc;
HINSTANCE mod = (HINSTANCE)GetModuleHandle(NULL);
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo(mod, "STATIC", &wc);
wc.hInstance = mod;
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
SetProp(parent, propname, (HANDLE)wc.lpfnWndProc);
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
if (!RegisterClass(&wc))
MessageBox(NULL, "error in register", "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,
parent,
NULL,
mod,
NULL);
if (hwnd == NULL)
MessageBox(NULL, "error in create", "error", MB_OK);
}
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);
}
};
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[] = "CodeBlocksWindowsApp";
//creating the window
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
DeleteFile(debugname);
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);
UpdateWindow(hwnd);
label label1(hwnd);
label1.SetText("oi");
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
heres the debug.txt file:
Code:
0x0081
0x0083
0x000c
0x0005
0x0003
0x0018
0x0046
0x0047
0x000c
0x000f
0x0085
0x0014
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0084
0x0002
0x0082
but why the WM_CREATE isn't executed?
-
December 29th, 2013, 10:12 AM
#41
Re: [win32] - creating controls using class's
but why the WM_CREATE isn't executed?
It is! The WM_CREATE msg isn't output to the file if you look at the code. The below is the replacement wndproc that will output all msg to file.
Code:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ofstream os(debugname, ios_base::app);
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), propname);
if (oldproc == NULL)
MessageBox(NULL, "null", "null", MB_OK);
os << "0x" << hex << setw(4) << setfill('0') << msg << endl;
switch(msg) {
case WM_CREATE:
//This doesn't work as the window hasn't been created!
SetWindowText(hwnd, "hello world");
break;
default:
break;
}
//If oldproc is NULL then use DefWindowProc - but shouldn't be!
return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
}
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
December 29th, 2013, 10:20 AM
#42
Re: [win32] - creating controls using class's
Originally Posted by 2kaud
It is! The WM_CREATE msg isn't output to the file if you look at the code. The below is the replacement wndproc that will output all msg to file.
Code:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ofstream os(debugname, ios_base::app);
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), propname);
if (oldproc == NULL)
MessageBox(NULL, "null", "null", MB_OK);
os << "0x" << hex << setw(4) << setfill('0') << msg << endl;
switch(msg) {
case WM_CREATE:
//This doesn't work as the window hasn't been created!
SetWindowText(hwnd, "hello world");
break;
default:
break;
}
//If oldproc is NULL then use DefWindowProc - but shouldn't be!
return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
}
yes you have right.. i have tested now with a message box and it's showed.
but now i have a new problem
how can i create variables(not static) for use them inside of window procedure?
i understand that the message loop must be static for put it inside of the class
please tell me more about these
-
December 29th, 2013, 10:36 AM
#43
Re: [win32] - creating controls using class's
The way you do this is to have a window property that contains the address of the class instance.
The code below demonstrates the idea. The label class constructor sets the value of text which is then displayed when WM_CREATE control message is processed.
Code:
#include <windows.h>
#include <fstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
static char propname[] = "Cambalinho";
static char classprop[] = "classaddr";
static char debugname[] = "debug.txt";
class label
{
private:
HWND hwnd;
string text;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ofstream os(debugname, ios_base::app);
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), propname);
label *inst = (label*)GetProp(GetParent(hwnd), classprop);
if (oldproc == NULL)
MessageBox(NULL, "null", "null", MB_OK);
os << "0x" << hex << setw(4) << setfill('0') << msg << endl;
switch(msg) {
case WM_CREATE:
MessageBox(NULL, inst->text.c_str(), "From class instance", MB_OK);
//This doesn't work as the window hasn't been created!
SetWindowText(hwnd, "hello world");
break;
default:
break;
}
//If oldproc is NULL then use DefWindowProc - but shouldn't be!
return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
label(HWND parent) {
text = "qwerty";
WNDCLASS wc;
HINSTANCE mod = (HINSTANCE)GetModuleHandle(NULL);
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo(mod, "STATIC", &wc);
wc.hInstance = mod;
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
SetProp(parent, propname, (HANDLE)wc.lpfnWndProc);
SetProp(parent, classprop, (HANDLE)this);
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
if (!RegisterClass(&wc))
MessageBox(NULL, "error in register", "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,
parent,
NULL,
mod,
NULL);
if (hwnd == NULL)
MessageBox(NULL, "error in create", "error", MB_OK);
}
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);
}
};
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[] = "CodeBlocksWindowsApp";
//creating the window
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
DeleteFile(debugname);
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);
UpdateWindow(hwnd);
label label1(hwnd);
label1.SetText("oi");
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
December 29th, 2013, 11:00 AM
#44
Re: [win32] - creating controls using class's
Code:
#include <windows.h>
#include <fstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
static char propname[] = "Cambalinho";
static char classprop[] = "classaddr";
static char debugname[] = "debug.txt";
class label
{
private:
HWND hndlabel;
string text;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), propname);
label *inst = (label*)GetProp(GetParent(hwnd), classprop);
if (oldproc == NULL)
MessageBox(NULL, "null", "null", MB_OK);
switch(msg) {
case WM_MOUSEMOVE:
SetWindowText(inst->hndlabel, "hello world"); //isn't changed
break;
default:
break;
}
//If oldproc is NULL then use DefWindowProc - but shouldn't be!
return oldproc ? CallWindowProc(oldproc, hwnd, msg, wParam, lParam) : DefWindowProc(hwnd, msg, wParam, lParam);
}
public:
label(HWND parent) {
text = "qwerty";
WNDCLASS wc;
HINSTANCE mod = (HINSTANCE)GetModuleHandle(NULL);
ZeroMemory(&wc, sizeof(WNDCLASS));
GetClassInfo(mod, "STATIC", &wc);
wc.hInstance = mod;
wc.lpszClassName = "CSTATIC";
// store the old WNDPROC of the EDIT window class
SetProp(parent, propname, (HANDLE)wc.lpfnWndProc);
SetProp(parent, classprop, (HANDLE)this);
// replace it with local WNDPROC
wc.lpfnWndProc = WndProc;
// register the new window class, "ShEdit"
if (!RegisterClass(&wc))
MessageBox(NULL, "error in register", "error", MB_OK);
hndlabel = CreateWindowEx(
WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
"CSTATIC",
"hello",
SS_LEFT|WS_CHILD|WS_VISIBLE,
0, 0, 100, 100,
parent,
NULL,
mod,
NULL);
if (hndlabel == NULL)
MessageBox(NULL, "error in create", "error", MB_OK);
}
COORD GetSize()
{
RECT LabelSize;
GetWindowRect(hndlabel,&LabelSize);
COORD crdSize={LabelSize.right-LabelSize.left,LabelSize.bottom-LabelSize.top};
return crdSize;
}
void SetText(string text)
{
char* chrText=(char*)text.c_str();
SetWindowText(hndlabel, chrText);
}
};
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[] = "CodeBlocksWindowsApp";
//creating the window
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
DeleteFile(debugname);
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);
UpdateWindow(hwnd);
label label1(hwnd);
//label1.SetText("oi");
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
i'm using the pointer: why the SetWindowText() isn't used? the inst->hndlabel can be the problem... but tell more please?
(i need use some functions inside of the window procedure)
-
December 29th, 2013, 11:12 AM
#45
Re: [win32] - creating controls using class's
You should also have a destructor for class label.
Code:
~label() {
DestroyWindow(hwnd);
hwnd = 0;
}
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|