Design problem in wrapping Windows's Window API - winapi

I'm writing an object-oriented window API wrapper for Windows in D, and I'm having a (non-language-specific) design problem.
Windows requires that all windows be previously registered with RegisterClass; extending an existing class requires replacing the window procedure. Furthermore, there seem to be two kinds of window handles: HWNDs that need to be disposed (via DestroyWindow), and HWNDs that don't (e.g. from other applications).
I have created a Window class, and so long as I'm just wrapping the ShowWindow, UpdateWindow, FindWindow, and other such methods, everything is fine and dandy. But as soon as I try to add a constructor with a className parameter to my class that calls CreateWindow, I run across a problem:
The given className must already have been registered by RegisterClass.
In order to register a new window class, I would need to make my subclasses of Window to somehow call RegisterClass before trying to create a new Window, either directly or indirectly.
In order for my design (and inheritance) to make sense, i would need to make sure that, for any given subclass of Window, all instances are actually instances of the same window class; namely, that all classNames from a particular subclass are identical. (This is because the window procedures for all instances of a particular window class need to be the same.)
The problem is, there's no way to have an abstract static method (in order for Window to be able to ask the subclasses for their class info, and to register them once), and so I am forced to say something like CreateWindow(this.className, ...) in order to create a new window, which easily becomes problematic if my subclasses don't respect this rule, and give me a different class name per instance of the window.
Furthermore, I need a one-to-one mapping between the WNDCLASS.lpfnWndProc field and my Window subclass's (overridden) WndProc method. This doesn't exactly work, though, if I'm forced to get the method pointer on a per-instance basis, since it breaks the entire OOP design and messes everything up.
While it's possible for me to enforce this consistency at run-time, it's a bit ugly, and so it's not a great solution.
So, long story short, does anyone have any idea of an elegant solution to the problem of creating an abstract static method? I'm thinking of some design patterns like Factory and whatnot, but I'm not sure if they fit here... if someone thinks they might , I would really appreciate a little explanation on how it would fit into the design.
Thank you!

The standard solution for this is to give the base class two window procedures, a static one and a virtual one.
The base class registers its class with the static window procedure. The static window procedure then invokes the virtual window procedure. Many people omit the HWND parameter from the virtual version since it can be obtained from the this pointer, but I'll leave it in just to simplify the story.
class Window
{
public:
virtual LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ return DefWindowProc(hwnd, uMsg, wParam, lParam); }
private:
static LRESULT CALLBACK StaticWndProc(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_NCCCREATE) {
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(
reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams);
}
Window *pThis = reinterpret_cast<Window*>(
GetWindowLongPtr(hwnd, GWLP_USERDATA));
LRESULT lres = pThis ? pThis->WndProc(hwnd, uMsg, wParam, lParam)
: DefWindowProc(hwnd, uMsg, wParam, lParam);
}
};
Derived classes override Window::WndProc.

The window proc doesn't have to be the same for all instances of a particular class name.
Typically, you'd use the RegisterClass function to set the default window proc for windows of that class. When you create a new window that uses the class but you want it to override the default handling, you create the window and then call SetWindowLongPtr(hwnd, GWL_WNDPROC, newWndProc), where newWndProc is a pointer to the new window's window proc.
The new window's window proc can then handle the messages that it wants to override, and call DefWindowProc for the rest.
To construct a window with a new class name, have the constructor copy the class info for the inherited class and create a new class that's identical to that one, except for the name. Then expose a method that will allow the client to change class-specific things. The API functions you're interested in would be GetClassInfoEx and SetClassLong, SetClassWord or SetClassLongPtr.
Inheritance still makes sense in this world because the default processing is the same for every window of a particular class, and inherited classes inherit the default processing from their parents.
You don't need anything like an abstract static method for this. All you need is the window handle. You can get the class name by calling GetClassName with the window handle, and then call GetClassInfoEx with the returned class name.

Wow, I certainly didn't expect this...
I searched for the phrase x86 thunks on Google. And, as it turns out, I wasn't the first person to come across this problem (surprise!).
The first hit was the exact problem and the solution to this question about Window Procs, even though it had nothing to do with my query (or at least, very little to do directly)... hope someone else finds it useful too.

Related

Finding handle for a button in the window of another program

I need some help. I wrote my questions at the end and will first explain what exactly my code is supposed to do:
I am making a program that will communicate with other programs. What I need my software to do is be able to click on a button on another program, and I believe the appropriate code to do this would be:
SendMessage(hWnd, Msg, wParam, lParam);
with
Msg = B_Click
wParam = 0;
lParam = 0;
however I am not sure how to get the hWnd which is the handle of a specific button on a specific window of another program that is running at the same time. I have read somewhere that I could possibly do the following:
HWND buttonHandle = FindWindowEx(hwndParent, hwndChildAfter, lpszClass, lpszWindow);
where:
HWND hwndParent = A handle to the parent window whose child windows are to be searched
HWND hwndChildAfter = if its null child windows are of the parent window are looked through
LPCTSTR lpszClass = (NOT SURE WHAT THIS IS)
LPCTSTR lpszWindow = (NOT SURE WHAT THIS IS)
I have a few issues with the FindWindowEX() function however.
Question 1: The window I am looking at has various buttons, so how would the function know which one of the 3 i am looking at?
Question 2: What are the lpszClass and lpszWindow variables and how might I get them?
Question 3: Is this even the right approach? If it's not, please point me to the right direction!
You don't need the handle of the button, you need the handle of its parent window. The button sends BN_CLICKED to its parent window. Look up the button's ID with spy++. Then use EnumChildWindows of the parent to look at all the child windows. For each child use GetWindowLong with GWL_ID to check its ID.

Child windows does not receive WM_DESTROY?

I packaged the winapi CreateWindowEx into a simple class. Since every window sharing a same wndProc(hwnd,msg,wparam,lparam), I put every window created by CreateWindowEx into a map to distribute msg, like this:
wndProc(hwnd, msg, wparam, lparam){
if(map[hwnd]!=nil){
switch(msg){
map[hwnd].wndProc(...)
}
}
}
And each time a window or its parent window being destroyed, remove it from the map:
case WM_DESTROY: delete(map, hwnd)
But things like buttons do not receive WM_DESTROY. I printed all msg in WM_NOTIFY and WM_COMMAND but i got noting.
So how can I remove those child windows form the map at the right time? Or a way distribute the msg without creating a hwnd map?
They certainly do get that message. But their window procedure is inside Windows, not inside your program. So you never see it. Something you can read in the MSDN documentation, note how WM_DESTROY doesn't get any special treatment. Nor generate a notification that your parent window can see.
Short from automatically removing all the child windows when you see the parent window destroyed, subclassing controls is a pretty standard requirement for C++ class library wrappers. Best to not invent your own btw, this has been done many times already.
So how can I remove those child windows form the map at the right time?
You have to subclass every window you create, either with SetWindowLongPtr(GWL_WNDPROC) or SetWindowSubClass(), then you will receive all of the WM_DESTROY messages.
Or a way distribute the msg without creating a hwnd map?
Frameworks like ATL and VCL handle that by dynamically allocating a thunk for each window and putting the object pointer right in the thunk, then use the thunk as the window procedure. That way, whenever the thunk is called, it passes the message directly to its associated object.

Creating a separate window against each click on push button

I am working on Windows GUI Application.There are 20 Push Buttons on my Window. Against each button click, I want to open up a new window for displaying some information. It can be anything which can display some information but since I am new to all this and I didn’t want to try anything complicated, I decided to go with the idea of creating a pop up window against each button click.
Now the problem that I am facing is that since there are 20 different windows, do I need to create 20 different window callback functions? Though there is only one control in the pop up window i.e. a Close sign, but even for that I need to have a CALLBACK function.
I had been trying with this but now this idea looks senseless. Is there any other option in which I can achieve the desired functionality?
Waiting for help.
If all of the windows should behave the same way, then you can create a single window procedure (what you're calling the CALLBACK function) that is shared by all of the pop-up windows.
Window procedures do not have to be unique to individual windows, but if multiple windows share the same window procedure, they will react identically to all messages that they receive.
For example:
// Message procedure for all pop-up windows.
LRESULT CALLBACK MyPopupWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
// handle any messages you want here in order to
// customize the behavior of your pop-up window
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
You specify a pointer to the MyPopupWndProc function when you register the window class for your pop-up windows (using the RegisterClassEx function), and then you pass the name of the registered window class when you call CreateWindowEx to create/display a pop-up window whenever one of the buttons on your main window is clicked.
Of course, if you're just wanting something simple for testing purposes, remember that you can always call the MessageBox function! No window procedures or class registration required.

how to route a message to the control's standard WNDPROC

When a standard window control (e.g. an "EDIT" control) is created, its WNDPROC is defined as part of the window class (i.e. "EDIT" has a specific WNDPROC that is designed to make the window display & behave as an edit-control).
MFC allows you to interact with such controls via their wrapper classes, such as a CEdit wrappers the specialized messages for an "EDIT" window control.
MFC further allows you to bind an instance of an "EDIT" window to a C++ subclass of CEdit, say a CMyEdit, where you can override inherited virtual functions of CEdit and CWnd, and you can define a message table to gain access / override messages sent to the window instance itself.
There is CWnd::Default(), which calls this->DefWndProc with the current message arguments. This appears to lookup the WNDPROC for the HWND it is associated with. So is this the correct answer: call DefWndProc() (or equally, Default()), which will hand it off to the WNDPROC of the windows control?
Obviously, this is different than other message table handlers which can return FALSE to indicate that they didn't handle the message, and MFC will automatically route the message up the class inheritance hierarchy to the next message handler for this message, or, I assume, to Default() to be handled by the native WNDPROC?
If I define an arbitrary message handler, say for WM_SETTEXT, what is the correct way to pass this message on to the "EDIT" WNDPROC?
I'd also love to know if there is a way to pass the message up to a superclass (C++ class hierarchy) for handling? Many OnXXX style handlers do have a way to do so, but is there a mechanism that works for ON_MESSAGE handlers?
class CDynamicMenuControlEdit : public CEdit
{
...
LRESULT OnSetText(WPARAM wParam, LPARAM lParam);
...
}
BEGIN_MESSAGE_MAP(CDynamicMenuControlEdit, CEdit)
...
ON_MESSAGE(WM_SETTEXT, OnSetText)
...
END_MESSAGE_MAP()
LRESULT CDynamicMenuControlEdit::OnSetText(
WPARAM wParam, // not used; must be zero
LPARAM lParam // window-text string (LPCTSTR)
)
{
if (m_bHasFocus)
{
// do normal thing
// !!! THIS IS MY QUESTION: IS THIS CALLING EDIT's WNDPROC, or ::DefWinProc()? !!!
return DefWindowProc(WM_SETTEXT, wParam, lParam);
}
...
}
Clarification
You can have multiple MFC subclasses at the C++ level -
so C inherits B inherits A, where A is an MFC class (e.g. CEdit).
Each of those can have an MFC message table - i.e. BEGIN_MESSAGE_MAP ... END_MESSAGE_MAP which can each have a handler for any arbitrary windows message, such as WM_MESSAGE(WM_SETTEXT, OnSetText) - and that OnSetText member is not necessarily virtual - just a static member (each MFC subclass can route that message in any arbitrary way).
My question is - since a WM_MESSAGE dispatch entry doesn't have a return value, how do I allow MFC to walk up the MFC dispatch tables from C to B to A before handing back to the real windows 'EDIT' class's wndproc?
Or are all such entries intended at the MFC design-level NOT to be walked? i.e. the most subclassed layer's dispatcher is intended to be the only one called? And if it wants to leverage an inherited member it has to manually make that call - MFC simply doesn't have any specific generic structure for this?
Calling Default() will cause the "normal" processing that would have happened in response to a message to occur. I'm not entirely clear on what you are trying to achieve, but it seems to me that calling Default() is what you want to do.
If you look at a lot of the handlers from Windows messages in the CWnd handlers (and handlers from classes derived from CWnd such as CEdit) you will see that they call Default().
Word to the wise, that Default() will actually use whatever parameters the original message had - you cannot change them.
You're doing it right. CWnd::DefWindowProc() uses the WINDOWPROC you subclassed from and will call the EDIT window's window procedure.

Class Styles in WNDCLASS, what does it reference to ? Win32

what does it class style means actually ? it confused me. this is from MSDN: style
Specifies the class style(s). This member can be any combination of the class styles.
typedef struct _WNDCLASS {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;
The class styles are properties that affect every instance of a window of that specific class. To clarify, let's compare window instance properties vs class properties below. Supposes you create a new windows class called MyCoolControl, and you create several instances of this:
Every instance will have its own location, window text, and enabled and visible state - these are window instance properties, and you can set these on one window independently of the others.
However, all instances of this control will share the same WndProc, as specified in the WNDCLASS that you use to create the class. They'll also have the same class properties, such as whether the windows receive double-click messages rather than two separate click messages (CS_DBLCLKS class style bit), or whether the window is completely redrawn when resized (CS_HREDRAW, CS_VREDRAW), or whether the windows have a drop-shadow (CS_DROPSHADOW). The full list of class styles are listed on MSDN here.
So, for example, if you want a window to have a border or not, that's a window style bit (WS_BORDER), and you specify it as a window style value in CreateWindow (or can change it later per-window with SetWindowLongPtr(GWL_STYLE)), and only that window is affected. But if you want to create a window that has a drop shadow, you specify that in the style member of the WNDCLASS, and it affects all instances of that class.
(There are some exceptions to this - the WndProc specified in the WNDCLASS is really the default wndproc for that class of windows; you can actually override it per-instance if you want to. But the big picture is still mostly the same: WNDCLASS and CS_ styles are across-the-board settings, while the WS_ ones and the parameters to CreateWindow are specific to that one window.)

Resources