How to use DialogBoxParam? - c++

I have a pre-made template resource dialog, and I want to use DialogBoxParam to display it, but I can't find any good examples over the internet. The dialog is a simple login dialog, so can someone explain how to build my lpDialogFunc and what to put in dwInitParam?

You've tagged this question as C++, but havn't specified any particular framework (such as ATL or MFC).
So, in the spirit of providing a c++ / OOP answer to the question, without using a framework, the first thing to do is to create a class to wrap the dialog box, as well as provide a way for the dialog proc to reliably retrieve the pointer to the class. The windows API is a C API and cannot call class members directly so it is necessary to create static methods that can then retrieve the classes this pointer from somewhere.
class MyDialog {
HWND _dlg;
public:
int RunModal(HINSTANCE resModule, UINT resId,HWND parent){
return DialogBoxParam(resModule,MAKEINTRESOURCE(resId),parent,&StaticDialogProc,(LPARAM)this);
}
protected:
static INT_PTR CALLBACK StaticDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam){
MyDialog* self;
if(uMsg == WM_INITDIALOG){
self = (MyDialog*)lParam;
self->_dlg = hwndDlg;
SetWindowLongPtr(hwndDlg,DWLP_USER,lParam);
}
else
self = (MyDialog*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
if(self)
return self->DialogProc(uMsg,wParam,lParam);
return FALSE;
}
virtual UINT_PTR DialogProc(UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_INITDIALOG:
OnInitDialog();
break;
case WM_COMMAND:
OnCommand(LOWORD(wParam),HIWORD(wParam),(HWND)lParam);
break;
default:
return FALSE;
}
return TRUE;
}
virtual void OnInitDialog(){
}
virtual void OnCommand(int id, USHORT notifyCode,HWND control){
EndDialog(_hdlg,id);
}
};
Now, there are hundreds of window messages that Windows can send to a dialog. Add handlers for each message to DialogProc and call a specific virtual function so derived classes can handle the message differently by overriding the virtual.
The critical messages to handle are usually WM_INITDIALOG which is sent as soon as the dialog is created, so is an ideal time to initialize any controls on the dialog - to populate drop down controls, or SetWindowText to initielize text boxes with default values.
and WM_COMMAND, which is sent by controls like buttons, when they are clicked, passing in their id, and this is where you would handle the OK and CANCEL buttons.
Once DialogBoxParam returns, the dialog and all its child controls has been destroyed, so you would typically extract all the input fields in the OnCommand handler and store them in class members before calling EndDialog.

Another use case for the second part of the question: "what to put in dwInitParam"?
If you prefer OO programming and do not want to use the global scope for your dialog box, you can pass this to the formal parameter dwInitParam.
Obtaining a pointer to the caller:
template< typename CallerT >
inline CallerT *GetDialogCaller(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (WM_INITDIALOG != uMsg) {
// Retrieves information about the specified window.
// 1. A handle to the window and, indirectly, the class to which the window belongs.
// 2. Retrieves the user data associated with the window.
return reinterpret_cast< CallerT * >(GetWindowLongPtr(hwndDlg, GWLP_USERDATA));
}
CallerT * const caller = reinterpret_cast< CallerT * >(lParam);
// Changes an attribute of the specified window.
// 1. A handle to the window and, indirectly, the class to which the window belongs.
// 2. Sets the user data associated with the window.
// 3. The replacement value.
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, reinterpret_cast< LONG_PTR >(caller));
return caller;
}
Delegating the message to the caller:
class Widget {
public:
static INT_PTR CALLBACK DialogProcDelegate(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
// Retrieve a pointer to the instance of Widget
// that called DialogBoxParam.
Widget * const widget = GetDialogCaller< Widget>(hwndDlg, uMsg, wParam, lParam);
// Delegate the message handling.
return widget->DialogProc(hwndDlg, uMsg, wParam, lParam);
}
INT_PTR Show() const {
return DialogBoxParam(nullptr, MAKEINTRESOURCE(IDD_WIDGET_SETTINGS), nullptr, DialogProcDelegate, reinterpret_cast< LPARAM >(this));
}
private:
INT_PTR DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
// Note that this method is not affected by our approach,
// i.e. this method will still receive a WM_INITDIALOG.
switch (uMsg) {
...
}
return FALSE;
}
};
The alternative puts the caller in global scope and is restricted to a single caller for all dialog boxes.

you can do something like this. The dwInitParam Specifies the value to pass to the dialog box in the lParam parameter of the WM_INITDIALOG message. You can pass any value or simply pass NULL
INT_PTR CALLBACK editDlg(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
return 1;
break;
}
return 0;
}
if(DialogBoxParam(hInst,MAKEINTRESOURCE(IDD_EDIT),hwndMain,editDlg,NULL)==IDOK)
{
}

Related

How to handle mouse clicks in CMainFrame

How can I detect in an "empty" CMainFrame mouse clicks? With empty I mean a MDI which has not yet any document/view.
I have tried to detect mouse clicks with:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg);
MDI main frame windows have an 'invisible' client window that occupies the client area of the main frame. This window is inaccessible using 'normal' class override techniques but, if that main frame window is derived from either CMDIFrameWnd or CMDIFrameWndEx, you can use its m_hWndMDIClient member (the HWND of that invisible window) to subclass it, by overriding its WindowProc.
I do this (actually, to draw in that client area) in an override of the main frame's UpdateWindow procedure, using a bool member variable (set to false on construction) to keep track of whether or not the subclassing has already been done.
Here's a possible solution (adapted from my own code) that will likely work for intercepting mouse clicks. (I tested it and did actually get the Beep() diagnostic on mouse clicks!)
// Local function pointer to store the 'original' (default) window procedure...
LRESULT (CALLBACK *DefCliPrc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = nullptr;
// Static definition of our override procedure...
static LRESULT CALLBACK ClientProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT answer = DefCliPrc(hWnd, uMsg, wParam, lParam); // First, call default proc.
if (uMsg == WM_LBUTTONDOWN) {
Beep(1000,1000); // Make a sound to show that it's working!
// <Insert your handling code here>
}
//...
// Intercept/handle other messages, as required ...
//...
return answer;
}
// Override of the UpdateWindow function, to enact the subclassing...
void MyMainFrame::UpdateWindow(void)
{
if (!funchange) { // Only do the sub-classing ONCE ...
DefCliPrc = (WNDPROC)(intptr_t)(::GetWindowLongPtr(m_hWndMDIClient, GWLP_WNDPROC));
::SetWindowLongPtr(m_hWndMDIClient, GWLP_WNDPROC, (intptr_t)(ClientProc));
funchange = true; // Set this 'flag' to prevent repetition!
}
CMDIFrameWnd::UpdateWindow(); // Should always call base class
return;
}

Lifespan of smart pointer objects declared and initialized inside WndProc message (WM_CREATE)

If I declare and initialize object within main window callback function like so:
LRESULT CALLBACK WndProc
(
HWND hWnd // handle to window of this process
, UINT msg // message constant
, WPARAM wParam // holder of message parameters
, LPARAM lParam // holder of message parameters
)
{
switch (msg)
{
case WM_CREATE:
{
std::unique_ptr<Foo> foo = std::unique_ptr<Foo>(new Foo);
}
break;
}
}
Will the object foo stay initialized after the break of WM_CREATE message? And if not, where is the best place to declare it so that it's scope is not limited by the case scope?
The foo object is creating controls in the main window by the way so I think the requirement is to let it live till the end of runtime.
I suspect it will not survive. I am thinking about declaring those as global variable (but I don't like that option for obvious reasons) or as static objects within the callback function (but outside the switch). But there might be better options I don't see, so I am seeking your advice.
Thank you for help!
Here's a workup of RbMm's suggestion, which I use myself in my own code. A smart pointer has little to offer here, so there's really not much point in using one. Please note that I have used C-style casts for brevity, but you can use reinterpret_cast if you prefer.
class MyWindowData { ... };
MyWindowData *window_data = new MyWindowData;
HWND hWnd = CreateWindow (... ... ..., (LPARAM) window_data);
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCCREATE:
CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
SetWindowLongPtr (hWnd, GWLP_USERDATA, cs->lpCreateParams);
break;
case NC_DESTROY:
MyWindowData *window_data = (MyWindowData *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
SetWindowLongPtr (hWnd, GWLP_USERDATA, 0);
delete window_data;
break;
}
// return something here;
}
You can then do:
MyWindowData *window_data = (MyWindowData *) GetWindowLongPtr (hWnd, GWLP_USERDATA);
to retrieve MyWindowData any time you need it, but check for zero being returned in case WM_NCCREATE is not the first message received by your WNDPROC as per the comments.

Why LRESULT CALLBACK is used in this function?

Recently, I've started to learn DX11 and I was trying to create message loops in WinAPI. I saw a LRESULT CALLBACK function from the tutorial that I haven't seen before. It is called in Window Procedure function. Here is the WndProc function and the MessageHandler function(the function that I'm talking about).
WndProc:
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch(umessage)
{
// Check if the window is being destroyed.
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
// Check if the window is being closed.
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
// All other messages pass to the message handler in the system class.
default:
{
return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
}
}
}
MessageHandler:
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch(umsg)
{
// Check if a key has been pressed on the keyboard.
case WM_KEYDOWN:
{
// If a key is pressed send it to the input object so it can record that state.
m_Input->KeyDown((unsigned int)wparam);
return 0;
}
// Check if a key has been released on the keyboard.
case WM_KEYUP:
{
// If a key is released then send it to the input object so it can unset the state for that key.
m_Input->KeyUp((unsigned int)wparam);
return 0;
}
// Any other messages send to the default message handler as our application won't make use of them.
default:
{
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
}
}
What I don't understand is, why we added the "LRESULT CALLBACK" part to the MessageHandler function? I know, we must add it to WndProc function, but I don't get the point of creating a new function and adding it a calling convention. What if we don't add any calling convention to the MessageHandler function? What if we didn't create the MessageHandler funciton and write the KEY_DOWN listeners to WndProc's switch-case statement?
These codes are in one class and ApplicationHandler pointer points to "this".
There is no obvious reason for SystemClass::MessageHandler to be declared as CALLBACK because it cannot be used as a message handler for Windows since it is not static. There is no reason for SystemClass::MessageHandler to be declared as CALLBACK in the code you showed.
About the CALLBACK (__stdcall):
Functions called from "within Windows" just have to be stdcall because Windows developers decided to write/compile Windows that it calls stdcall functions. In theory, any CC could be used, but Windows and your code must have the same.
Your own function won´t need it if you´re using it only in your own code in your program.
LRESULT (some int/pointer-like thing) is just the return type.
The reason for not just writing int (or something like that) is that LRESULT is a int with a certain length etc., and if MS decides to change it for some reason, they only need to change the definition of LRESULT, but not every function which has a LRESULT return type.

Subclassing an edit control from a user defined class/pointer-to-member-function

I think I've fallen in the same trap as many before me where I try to impose a nice OO methodology on win32 API programming. No MFC, no AFX, I'm not even using VC++, I'm using C::B with gcc.
I think what I'm trying to do is impossible, but since MFC exists (although I'm not using it) there must be some way.
I've created a class to contain several window controls. It implements handlers for WM_CREATE and WM_COMMAND, and keeps track of all the associated data around my small group of controls (ID codes and HWNDs).
It works great for buttons, static controls, even light GDI methods, but it all breaks down when I try to subclass an edit control.
Really, I just want to capture the "enter" key, but as anybody who's been down that road before will attest, when an edit control has focus, the parent window doesn't receive WM_KEYDOWN or WM_COMMAND, we are left to implement our own proc. Super lame.
OK, so subclassing an edit control is fine, if the editProc is global or static. I know that is because SetWindowLongPtr needs a function address, and that concept is nebulous for a member function.
So the object of my class is declared as "static" inside the parent WndProc. But the function is not "static" because then I wouldn't have access to non-static data members (completely defeating the purpose of this exercise). I'm hoping that because the objest is itself static, I should be able to properly define the address of one of its member functions.
Readers that have tried this before will either have given up and used MFC or something else, or perhaps have found a clever work-around.
I'll let this sample code do the rest of the talking: (simplified - will not compile as such)
/**** myprogram.c ****/
#include "MyControlGroup.h"
int winMain(){ // etc... }
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// object is static becuse it only needs to be initialized once
static MyControlGroup myControl;
if (msg == WM_CREATE)
myControl.onWMCreate(hWnd);
else if (msg == WM_COMMAND)
myControl.onWMCommand( wParam, lParam );
else if (msg == WM_DESTROY)
PostQuitMessage(0);
return DefWindowProcW(l_hWnd, l_msg, l_wParam, l_lParam);
}
The header file for my class:
/**** MyControlGroup.h ****/
class MyControlGroup
{
private:
HWND m_hWndParent;
HWND m_hWndEditBox;
int m_editBoxID;
public:
MyControlGroup();
void onWMCreate(HWND);
void onWMCommand(WPARAM, LPARAM);
// want to find a way to pass the address of this function to SetWindowLongPtr
LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
...and the implementation:
/**** MyControlGroup.cpp ****/
static int staticID = 1;
MyControlGroup::MyControlGroup()
{
m_editBoxID = staticID++;
}
void MyControlGroup::onWMCreate(HWND hWnd)
{
// My control group has buttons, static controls, and other stuff which are created here with CreateWindowW. It also has an edit control:
m_hWndEditBox = CreateWindowW(L"EDIT", L"initial text", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 150, 20, hWnd, (HMENU)m_editBoxID, NULL, NULL);
/*
To subclass the edit control, I need a pointer to my customized proc. That means I
need a pointer-to-member-function, but SetWindowLongPtr needs a pointer to global or
static function (__stdcall or CALLBACK, but not __thiscall).
*/
// I'd like to do something like this, adapted from a great write-up at
// http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
LERSULT (MyControlGroup::*myEditProcPtr)(HWND, UINT, WPARAM, LPARAM);
myEditProcPtr = &MyControlGroup::myEditProc;
// Up to now it compiles ok, but then when I try to pass it to SetWindowLongPtr, I get
// an "invalid cast" error. Any ideas?
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProcPtr);
}
void MyControlGroup::onWMCommand(WPARAM wParam, LPARAM lParam){ /* process parent window messages. Editboxes don't generate WM_COMMAND or WM_KEYDOWN in the parent :''( */}
LRESULT MyControlGroup::myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// process messages like IDOK, WM_KEYDOWN and so on in the edit control
}
Even once I get this done, I'll still need to figure out a way to pass the address of the parent WndProc to myEditProc for the return value, but until I get past this there is no point in worrying about that.
Thanks in advance for reading!
myEditProc needs to be a static function.
Once you've done that you can pass the address of the function directly without going through the intermediate variable:
static LRESULT myEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
...
SetWindowLongPtr(m_hWndEditBox, GWLP_WNDPROC, (LPARAM)myEditProc);
To access your class data from the static function, you can save it in the userdata field of the edit control, e.g.:
// before sub-classing the control
SetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA, (LPARAM)this);
// in the sub-class procedure
MyControlGroup* pThis = (MyControlGroup*)GetWindowLongPtr(m_hWndEditBox, GWLP_USERDATA);
But as #K-ballo suggested, SetWindowSubclass is definitely the way to do this unless you want compatibility with pre-XP. It handles the sub-classing procedure for you automatically, lets you associate a userdata pointer (e.g. this) that is automatically passed to the sub-class procedure, and safely handles removing the sub-class at the end.

attaching WNDPROC function from child class

I have a problem with attaching a windows procedure to a window.
I have a baseclass called BaseWindow, that uses GWPL_USERDATA to call a virtual function called HandleMessage() of the child classes.
However, if i try to change the window procedure without creating a custom Window Class, it gives a type error from the child procedure to long.
Here's the code:
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BaseWindow *pThis = NULL;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (BaseWindow*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
pThis->m_hwnd = hwnd;
}
else
{
pThis = (BaseWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (pThis)
{
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{return 0;};
PlayList Class : BaseWindow
SetWindowLong(m_hwnd, GWL_WNDPROC,(long) HandleMessage); //Error
LRESULT PlayList::HandleMessage(UINT message,WPARAM wParam,LPARAM lParam) //Need to attach this window procedure
{}
It works if the child procedure is static, however I use non static members in that procedure.
I want to subclass a common control, while using this base class (because a lot of code is redundant), is it possible?
Here's the whole code for the base class: http://pastebin.com/ME8ks7XK
The compiler doesn't like your declaration for HandleMessage, it isn't static. It's missing CALLBACK too, not good.
Not sure why you are trying to do this, the whole point of your WindowProc() function is to get the message forwarded to a virtual HandleMessage() method. At best you'd use WindowProc in your SetWindowLong() call instead of HandleMesssage. Or just specify it directly in the CreateWindowEx() call.
From MSDN:
An application subclasses an instance of a window by using the SetWindowLong function. The application passes the GWL_WNDPROC flag, the handle to the window to subclass, and the address of the subclass procedure to SetWindowLong. The subclass procedure can reside in either the application's executable or a DLL.
So, you should write this:
SetWindowLong(m_hwnd, GWL_WNDPROC,(long) & HandleMessage);
But this doesn't compile again! the reason: all non-static member functions have hidden this parameter (pointer to owner class). So, you HandleMessage doesn't fit the WindowProc declaration.