Win32 API coding: A Wrapper class for Window Creation
category: general [glöplog]
Is there any experienced win32 api coders that can give me some usefull information about win32 wrapper classes?.. I guess this may not be the best place to ask, but i'll do it anyway.. Also I've read several tutorials about wrapper classes but noone seems to inherit the design i want. i want it to be easy, like when making new controllers, I want as little code as possible.
some cues:
- message crackers
- non-static wndProc
i think i may have it working very soon, i just thought i would ask someone here if they've been working on this before and what difficulties they may have had and what they're solutions they found etc.. - thanks
some cues:
- message crackers
- non-static wndProc
i think i may have it working very soon, i just thought i would ask someone here if they've been working on this before and what difficulties they may have had and what they're solutions they found etc.. - thanks
Please ask a specific question.
If you want as little code as possible winapi is definitely not the way you want to go. Use a widget toolkit such as QT,GTK+ or wxWidgets. Or If you don't mind managed code Windows Forms.
Quote:
I guess this may not be the best place to ask
good observation, now go ask google.
Hm. Object Windows Library is a wrapper for WinAPI:
http://en.wikipedia.org/wiki/Object_Windows_Library
http://en.wikipedia.org/wiki/Object_Windows_Library
Quote:
Quote:
I guess this may not be the best place to ask
good observation, now go ask google.
Hahaha! Definitively!
well.. i was very specific on this topic right before i pressed submit and got a error message saying something like that i was not logged in anymore.
anyway.. im not gonna use wxWidgets or any libraries like that. it was meant to be a Win32 API coding question only, it seems like there arent that many people who are very fond of this kind of stuff. :P
anyway.. im not gonna use wxWidgets or any libraries like that. it was meant to be a Win32 API coding question only, it seems like there arent that many people who are very fond of this kind of stuff. :P
I never really got comfortable with wrapping the shit up, so I've just written my windows in pure win32. I'm doing the "non-static wndprocs" (or usually in my case "non-global wndprocs") only when I need to be able to create more than one window per wndproc (through GWLP_USERDATA or some shit). I usually don't bother with those fancy message cracker thingies.
See Raymond Chen's skeleton code if you need something simple:
http://blogs.msdn.com/oldnewthing/archive/2005/04/22/410773.aspx
See Raymond Chen's skeleton code if you need something simple:
http://blogs.msdn.com/oldnewthing/archive/2005/04/22/410773.aspx
ok and thanks kusma. ill check the code tomorrow since im too tired for reading ... i was working on a "non-static" method but got some problems, i cant remember what problems it was, i dont think i really knew what happened because some windows didnt behave the way they should have behaved. i had to rewrite the whole thing again. bah time to sleep. ill probably be writing something in here again tomorrow.
Ok. If you really want to use winapi here's my non-static approach to WNDPROC:
Of course in your WNDCLASSEX you specify staticWindowProc and then remember to pass Win32_Application/your_class_name pointer (usually 'this') as the last parameter of CreateWindowEx().
Code:
LRESULT CALLBACK Win32_Application::staticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Win32_Application *thisApp;
if(uMsg == WM_CREATE)
{
thisApp = (Win32_Application*)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)thisApp);
}
else
thisApp = (Win32_Application*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if(thisApp == NULL)
return DefWindowProc(hWnd, uMsg, wParam, lParam);
return thisApp->windowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK Win32_Application::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
Of course in your WNDCLASSEX you specify staticWindowProc and then remember to pass Win32_Application/your_class_name pointer (usually 'this') as the last parameter of CreateWindowEx().
im doing the same thing masterm.
im not sure what the fuck is going on here.
the main window draws over the child.
the main window draws over the child.
You might also want to consider using WM_NCCREATE and WM_NCDESTROY instead of WM_CREATE and WM_DESTROY as NCCREATE is issued before CREATE and NCDESTROY is issued after DESTROY. Let's you catch some more messages during creation and destruction.
I'd give you some of my old code if I had it on the laptop. I'm with Kusma on this one though, go see if you can put the problem in a less 'specific' corner and if need really be, learn how the different window types differ from eachother by experience and lift the common part to a wrapper base once you feel confident.
i started this project from scratch again.
this is how my cpp file looks like:
and the declarations looks like this:
so the problem i have right now is that the parent window is drawing over the child window. like the screenshot i pasted yesterday. im not sure what is wrong, the rest of the code is working okay.
this is how my cpp file looks like:
Code:
#include "Window.h"
WndBase::WndBase(HINSTANCE hInst)
{
hInstance = hInst;
style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
exStyle = 0;
}
int WndBase::Register()
{
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = NULL;
wc.lpfnWndProc = msgRouter;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = className;
if(!RegisterClassEx(&wc))
{
MessageBox(0, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
return 0;
}
}
void WndBase::Create(HWND hwndparent, int _x, int _y, int _width, int _height)
{
exStyle = WS_EX_CLIENTEDGE;
x = _x;
y = _y;
width = _width;
height = _height;
hWndParent = hwndparent;
hMenu = 0;
hWnd = CreateWindowEx(exStyle, className, windowName, style, x, y, width, height, hWndParent, hMenu, hInstance, (void *)this);
}
void WndBase::SetHwnd(HWND hwnd)
{
hWnd = hwnd;
}
HWND WndBase::GetHwnd()
{
return hWnd;
}
void WndBase::ShowWindow(int cmd)
{
::ShowWindow(hWnd, cmd);
UpdateWindow(hWnd);
}
LRESULT CALLBACK WndBase::msgRouter(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
WndBase *wnd = 0;
if (msg == WM_NCCREATE)
{
wnd = reinterpret_cast <WndBase *> ((long)((LPCREATESTRUCT)l)->lpCreateParams);
SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)wnd);
wnd->SetHwnd(hwnd);
}
else
wnd = reinterpret_cast <WndBase *> (GetWindowLong(hwnd, GWL_USERDATA));
if (wnd == NULL)
return DefWindowProc(hwnd, msg, w, l);
return wnd->wndProc(hwnd, msg, w, l);
}
WndMain::WndMain(HINSTANCE hInst) : WndBase(hInst)
{
className = TEXT("WndMainClass");
windowName = TEXT("WndMain");
wc.style |= CS_HREDRAW | CS_VREDRAW;
}
LRESULT CALLBACK WndMain::wndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
switch(msg)
{
case WM_CREATE:
break;
case WM_PAINT:
OnPaint();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, w, l);
}
return 0;
}
void WndMain::OnPaint()
{
RECT rect;
HDC hDC = GetDC(hWnd);
PAINTSTRUCT PaintStruct;
BeginPaint(hWnd, &PaintStruct);
GetClientRect(hWnd, &rect);
DrawText(hDC, "Hello Parent!", 13, &rect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
EndPaint(hWnd, &PaintStruct);
ReleaseDC(hWnd, hDC);
}
WndChild::WndChild(HINSTANCE hInst) : WndBase(hInst)
{
className = TEXT("WndChildClass");
windowName = TEXT("WndChild");
style |= WS_CHILD;
wc.style |= CS_HREDRAW | CS_VREDRAW;
}
LRESULT CALLBACK WndChild::wndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
switch(msg)
{
case WM_CREATE:
break;
case WM_PAINT:
OnPaint();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, w, l);
}
return 0;
}
void WndChild::OnPaint()
{
RECT rect;
HDC hDC = GetDC(hWnd);
PAINTSTRUCT PaintStruct;
BeginPaint(hWnd, &PaintStruct);
GetClientRect(hWnd, &rect);
DrawText(hDC, "Hello Child!", 12, &rect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
EndPaint(hWnd, &PaintStruct);
ReleaseDC(hWnd, hDC);
}
and the declarations looks like this:
Code:
#include <windows.h>
class WndBase
{
public:
WndBase(HINSTANCE);
int Register();
void Create(HWND hwndparent, int _x, int _y, int _width, int _height);
protected:
static LRESULT CALLBACK msgRouter(HWND, UINT, WPARAM, LPARAM);
virtual LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM) = 0;
public:
void SetHwnd(HWND);
HWND GetHwnd();
void ShowWindow(int);
protected:
HWND hWnd;
HINSTANCE hInstance;
WNDCLASSEX wc;
HWND hWndParent;
HMENU hMenu;
LPCSTR className;
LPCSTR windowName;
int style;
int exStyle;
int x, y;
int width, height;
};
class WndMain : public WndBase
{
public:
WndMain(HINSTANCE hInst);
void OnPaint();
protected:
LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
};
class WndChild : public WndBase
{
public:
WndChild(HINSTANCE hInst);
void OnPaint();
protected:
LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
};
so the problem i have right now is that the parent window is drawing over the child window. like the screenshot i pasted yesterday. im not sure what is wrong, the rest of the code is working okay.
what i mean by that is that something is happening either in the DrawText function in the MainWindow or somewhere else, it seems like the child window's client is overdrawn when moving the child-window over the mainwindow's text.
Maybe something with the WM_BACKGROUND messages?! Otherwise maybe some drawing function gets a wrong window handle...
yeh, it may be that. the message-routing may not be working properly i think.
hmm. the problem does not occur when i remove the WS_CHILD style in the WNDCLASSEX structure. so, obviously doesnt it have anything to do with the messagehandler or something..
i found it! there was just a flag i needed to have for the parent window. its called WM_CLIPCHILDREN and it prevents areas occupied by child windows from being drawn on.
WM_CLIPCHILDREN? I knew microsoft is evil, but thats just.. i mean, cmon THINK ABOUT THE CHILDREN!
OO pervs
Seems to be pure joy opening a simple crappy window with WinAPI. And no, I wouldn't claim it's any cleaner with X11 for that matter. I guess you have your reasons for doing this but overall wouldn't it be sensible to use some lib for doing this - someone else has already taken the trouble of debugging on several machines?
sorry but,
what a load of rubbish.. All this crap to open a window... :-( Surely wouldn't you rather use something else instead ?
what a load of rubbish.. All this crap to open a window... :-( Surely wouldn't you rather use something else instead ?