0
void Base::RegisterWnd(HINSTANCE hInstance)
{
ZeroMemory(&WndCls, sizeof(WNDCLASSEX));
WndCls.cbSize = sizeof(WNDCLASSEX);
WndCls.hbrBackground = (HBRUSH)COLOR_WINDOW;
WndCls.hCursor = LoadCursor(NULL, IDC_ARROW);
WndCls.hIcon = LoadIcon(hInstance, NULL);
WndCls.hIconSm = LoadIcon(hInstance, NULL);
WndCls.hInstance = hInstance;
WndCls.lpfnWndProc = CallWindowProc; << What should i put here
}

I am trying to register the window class by using object oriented method. I have no idea what should I put for the lpfnWndProc in the class cpp. For the header file, this is how it looks like

#pragma once
#ifndef BASE_H
#define BASE_H

#include <Windows.h>
#include <windowsx.h>

class Base
{
HWND hWnd;
WNDCLASSEX WndCls;
public:
Base();
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void RegisterWnd(HINSTANCE hInstance);
void CreateWnd();
void ShowWnd();
~Base();
};

#endif

Please correct me if I am doing anything wrong. Still learning. Sorry and thanks :)

Josh Lcs
  • 55
  • 5
  • 3
    lpfnWndProc must be global function (or static class function). The only data which can help to identify window instance is `HWND hWnd` parameter. So, you need some global map, which keeps (HWND, Base*) pairs. Using this map, you can call `Base` instance member from global lpfnWndProc. – Alex F Oct 30 '14 at 09:45
  • 2
    I would strongly recommend against reinventing the wheel. If you absolutely must implement your own C++ wrapper around the Windows API, you could always check out the MFC implementation. You should also acknowledge that, if you're having difficulty understanding the difference between a function pointer and a member function pointer, you may not be ready to write framework code. – IInspectable Oct 30 '14 at 09:49
  • 1
    @IInspectable I am still studying on C++ and I dont see anything wrong of learning if I am not good at it. Thanks for the MFC suggestion though. – Josh Lcs Oct 30 '14 at 10:02
  • @Josh Lcs I don't think IInspectable was exactly _recommending_ MFC. It's just that if you absolutely MUST use Microsoft's API to code GUIs in C++, then MFC is a better choice than the bare WIN32 API. It's still a poor choice, though. Better options would be wxWidgets or Qt. Both of these are cross-platform GUI toolkits that are much nice to use than either the WIN32 API or MFC. – antred Oct 30 '14 at 10:10
  • @antred: I recommended reading the MFC implementation to get a feeling of what is required to get this going. Other than that, there really is **nothing** wrong with using the Windows API or MFC or WTL to write GUI code. While Qt makes it more comfortable to write GUI code, it generally produces extremely low quality GUIs, that are impossible to use without a pointing device. When it comes to maintaining GUI code, Windows API code is generally a lot more maintainable than Qt code. The ease of setting up signal-slot-connections comes at the expense of producing lots of invisible code. – IInspectable Oct 30 '14 at 11:21
  • @IInspectable I very much disagree with your assertion that Qt results in low quality GUIs. What are you basing that claim on? – antred Oct 30 '14 at 13:02
  • @antred: *"GUIs, that are impossible to use without a pointing device"*. There's a lot of bad in Qt GUIs, like failing to accept any input on occasion, failing to implement established OS UI guidelines (the *Default button* concept usually never quite works), setting a dialog's initial size **after** it has already been displayed, generally sluggish GUIs (due to slow software rendering), state machines implementing control logic that get tied up in impossible states sooner or later, and so on. Most of these issues are more apparent when you're using the keyboard exclusively. – IInspectable Oct 30 '14 at 13:21
  • @antred the problem with Qt is that it doesn't use windowed controls. It's not native. Not Win32. – David Heffernan Oct 30 '14 at 20:43
  • @AlexFarber: instead of using a separate lookup map, you can simply pass the `Base*` pointer in the `lpParam` parameter of `CreateWindow/Ex()` and have `WndProc()` store that pointer in the `HWND` itself using `SetWindowLongPtr(GWL_USERDATA)` when it receives `WM_NCCREATE` or `WM_CREATE`, and then use `GetWindowLongPtr()` to retrieve the `Base*` pointer from the `HWND` for any other message received. For the few messages that might arrive before `WM_NCCREATE`, just pass them to `DefWindowProc()`, chances are you will never want your class to process them. – Remy Lebeau Oct 31 '14 at 01:34
  • @Remy: One notable exception is [`WM_GETMINMAXINFO`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms632626.aspx), which dialogs with dynamic control layout will want to process. A more robust and future proof solution is to set up a CBT hook, and store the window instance pointer in the `HCBT_CREATEWND` handler. This is what MFC does, and why it is immune to window message additions and reordering in a future OS release. – IInspectable Oct 31 '14 at 20:52
  • @IInspectable: A CBT hook may be a bit overkill for that. I would probably just use a thread-local variable instead. In any case, `WM_GETMINMAXINFO` is not always received before `WM_NCCREATE`. See http://stackoverflow.com/a/1741348/65863 – Remy Lebeau Oct 31 '14 at 21:03
  • @Remy: Registering a CBT hook for a single thread isn't all that bad. It boils down to a user-provided callback for a number of API calls. And since you already discovered, that the order of messages is not strictly defined, a CBT hook is really the cleanest solution if you need to initialize data prior to the first message being passed to a window procedure. – IInspectable Nov 03 '14 at 08:32

1 Answers1

2

Declare the following outside any class:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

and define it elsewhere

WndCls.lpfnWndProc = WndProc; // address of your window procedure

WndProc is supposed to have a switch-case within to take care of the events or messages that you need to handle in the specific window class function ( a C function or a class static method)

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • 1
    I doesn't necessarily have to be a C function, but it can't be a *thiscall* ( http://en.wikipedia.org/wiki/X86_calling_conventions#thiscall ). If the OP wants the lpfnWndProc to be a method, it has to be a static method, though. – antred Oct 30 '14 at 09:44
  • Thanks for the quick reply. Do I need to add it to the main.cpp? No other way to add all the registering of window class into a single class? – Josh Lcs Oct 30 '14 at 09:45
  • -1 Demanding a free function, without even mentioning a static class member fails to address the OP's question. A free function necessarily needs to break data encapsulation, a required feature of object oriented programming. – IInspectable Nov 08 '14 at 12:04