I'm just starting to experiment with win32 and I've run into a problem.
BOOL CALLBACK UnsavedChangesProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND dHandle = GetActiveWindow();
switch (msg)
{
case WM_INITDIALOG:
MessageBox(NULL, "In InitDialog", 0, 0);
SetDlgItemText(dHandle, 1004, ("There are unsaved changes to \""));
char error[10];
sprintf_s(error, "%d", GetLastError());
MessageBox(NULL, error, 0, 0);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDSAVE:
DoFileSave(hwnd);
EndDialog(hwnd, TRUE);
PostQuitMessage(0);
break;
case IDEXIT:
EndDialog(hwnd, TRUE);
PostQuitMessage(0);
break;
}
break;
case WM_CLOSE:
EndDialog(hwnd, FALSE);
break;
default:
return FALSE;
}
return TRUE;
}
The GetLastError() returns 1421, control ID not found, but the ID (1004) definitely corresponds to the static control I'm trying to alter. I've also tried calling the function with the control name (IDC_STATIC_UNSAVED) with no luck. The strange part is that if I move the function call to where dHandle is declared (or get rid of dHandle and just call GetActiveWindow() inside the function there) the text is changed but it flickers because the function is being called every time the message loop iterates.
Is there a simple reason that this shouldn't work that I'm missing?
Any help will be appreciated.
Edit: Here is an image of the Resource Symbols: Resource Symbols
And here is an image of the Dialog Template: Dialog Template
Note that all of the other controls work as expected.
The dialog window is passed to your handler in the hwnd parameter. There is no need to call GetActiveWindow() - in fact, that will give you the HWND of another window when the dialog is not the active window.
So, replace
HWND dHandle = GetActiveWindow();
SetDlgItemText(dHandle, 1004, ("There are unsaved changes to \""));
with
SetDlgItemText(hwnd, 1004, "There are unsaved changes to \"");
I agree with Sid S.
Besides changing the first parameter of SetDlgItemText from dHandle to hwnd, I would also suggest using IDC_STATIC_UNSAVED instead of the hardcoded value 1004. So, the SetDlgItemText() call becomes:
SetDlgItemText(hwnd, IDC_STATIC_UNSAVED, ("There are unsaved changes to \""));
Related
I'm struggling properly creating a dialog box.
The first problem was getting the dialog box itself visible. When displaying a dialog it did only show controls inside of the dialob box, but the dialog box itself were invisiblem but it was still possible to press the close button. I fixed this by adding a custom class name to the dialog boxes properties and registering the class. Does someone know what exactly the problem was? A colleague of mine didn't need to explicit register the class and add it to the dialog boxes properties.
But my current problem is as follows:
I have this callback function:
static BOOL CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
MessageBox(NULL, L"init dialog", L"Message Box", NULL);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
MessageBox(NULL, L"close dialog", L"Message Box", NULL);
break;
case WM_DESTROY:
MessageBox(NULL, L"destroying dialog", L"Message Box", NULL);
break;
}
return TRUE;
}
and this initiation of a new dialog box:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
TCHAR szTitle[MAX_LOADSTRING] = TEXT("This is the DialogBox Title"); // Titelleistentext
TCHAR szWindowClass[MAX_LOADSTRING] = TEXT("MyDialogBoxClass"); // Klassenname des Hauptfensters
g_hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern
if (!MyRegisterClass(hInstance, szWindowClass))
{
return FALSE;
}
hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG_FTPHELPER), NULL, DialogProc);
if (!hWnd)
{
return FALSE;
}
SetWindowText(hWnd, szTitle);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if (g_hWndCommandBar)
{
CommandBar_Show(g_hWndCommandBar, TRUE);
}
return TRUE;
}
When displaying a new dialog box it doesn't call the "DialogProc" function not even once, never, it makes me sick...
Does someone know the answer to this problem?
best greetings and thank you for your help!
Your DialogProc function always returns TRUE, meaning that it handled whatever message it received. However, you only actually handle three messages, and there are many others (such as WM_CREATE) that are called by the system in order to 'set up' the dialog window.
You should only return TRUE if you have completely handled the message, and FALSE otherwise, so that the system can call the default procedure for messages that you don't handle.
From the Microsoft documentation:
Typically, the dialog box procedure should return TRUE if it processed
the message, and FALSE if it did not. If the dialog box procedure
returns FALSE, the dialog manager performs the default dialog
operation in response to the message.
The test case is very simple. I want to set the contents of a Picture Control (IDC_STATIC1) upon the pressing of a button (IDC_BUTTON2) to a bitmap resource (IDB_BITMAP1). The problem I'm encountering is that when I press the button, the Picture Control doesn't load the image. I have verified that the button press IS being registered properly and the return value from LoadImage is NOT null.
The following code is the message handler for the dialog:
BOOL WINAPI DialogProc2(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON2)
{
HBITMAP bmp;
bmp = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
if (bmp == NULL)
{
MessageBox(NULL, "Error", "ERROR", MB_OK);
return TRUE;
}
SendDlgItemMessage(hWindow, IDC_STATIC1, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
//placing a MessageBox here proves that the button press is being registered properly and that the message is being sent, but nothing is happening...
}
return TRUE;
}
return FALSE;
}
It would seem the "Name" property of the Picture Control was set to "IDC_STATIC1" but the "ID" property was set to "IDC_STATIC". Changing it to "IDC_STATIC1" solved the issue.
I don't really get how to use HWND in c++.
I want to press a button and it should start a thread with a code running.
But I never receive the command for button click in an other callback.
So I did some debugging and it seems like that _wndInstance->GetWndHWND() returns something not valid. The method returns a private field which has it stored.
If you look a case WM_CREATE, the window content added will not show up with _wndInstance->GetWndHWND(). But if I just use hwnd from the parameters, it does work. But how is that possible if my first test-check validates that they are the same??
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (_wndInstance->GetWndHWND() == hwnd)
cout << "same" << endl; // Code is getting here!
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
{
_wndInstance->CreateWndContent(_wndInstance->GetWndHWND()); // not working, but hwnd is!
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
EDIT:
_wndInstance is an instance of a mainwindow class I wrote.
Part of mainWindow header:
private:
HWND _wndHwnd;
public:
HWND GetWndHWND();
MainWindow cpp:
HWND MainWindow::GetWndHWND()
{
return _wndHwnd;
}
_wndHwnd is set in a private method which creates the window:
_wndHwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"\"Xbox controller on WINDOWS\" Manager",
WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, // no maximize box
CW_USEDEFAULT, CW_USEDEFAULT, 450, 370,
NULL, NULL, hinstance, NULL);
if (_wndHwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return;
}
ShowWindow(_wndHwnd, nCmdShow);
UpdateWindow(_wndHwnd);
WM_CREATE is sent before CreateWindowEx() returns, and thus before your assignment happens. You will need to restructure your code so that the HWND is only used after it is assigned to _wndHwnd.
If you don't need to do anything between WM_CREATE and the beginning of the message loop, you can just drop your WM_CREATE handler. That depends on how your code will work in the future.
But a safer approach would be to assign _wndHwnd in your WM_CREATE handler (or even WM_NCCREATE), since you have it available as the hwnd parameter to your window procedure, and it would handle other messages sent between the window creation and the variable assignment. You can even pass _wndInstance as the last parameter to CreateWindowEx() and access it from WM_CREATE; see this for details.
I am trying to implement a chat window on a menu item click in the main window in win32. I have created a main window and am handling the chat window in the following way :
int CALLBACK TextChat::TextChatDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LPDRAWITEMSTRUCT pdis;
static HBRUSH hBrush;
static COLORREF GrayColor;
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, 1);
return true;
break;
case WM_INITDIALOG:
{
CentreWindow(hwndDlg);
ShowWindow(hwndDlg,SW_SHOW);
UpdateWindow(hwndDlg);
return TRUE;
}
}
return 0;
}
int TextChat::DoDialog()
{
//CreateWindowEx(
return DialogBoxParam(this->m_pApp->m_instance,MAKEINTRESOURCE(IDD_CHAT_DIALOG),
NULL, (DLGPROC) TextChatDlgProc, (LONG) this->m_pCC);
}
And from my main window on menu item clic, i am doing it the following way :
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case ID_TEXT_CHAT:
if(thisClass->m_pTextChat == NULL)
thisClass->m_pTextChat = new TextChat(thisClass->m_pApp,thisClass);
thisClass->m_pTextChat->DoDialog();
So i am using VS2008 and while debugging, the debugger goes inside TextChatDlgProc , but never goes inside WM_INITDIALOG and returns just like that. Hence, the chat window (resource IDD_CHAT_DIALOG) never get displayed. Any pointers towards resolving this problem is greatly appreciated. TIA
Regards,
grv
You say in a comment that the dialog has a rich edit control. That's the key!
You have to load the relevant library manually before these controls can be used. One of these:
LoadLibrary(TEXT("Msftedit.dll")); // for MSFTEDIT_CLASS
LoadLibrary(TEXT("Riched32.dll")); // for RICHEDIT_CLASS 3.2
LoadLibrary(TEXT("Riched20.dll")); // for RICHEDIT_CLASS 2.0
You can do that just once from WinMain().
Your TextChatDlgProc() needs to call DefWindowProc() for unhandled messages return FALSE for unhandled messages (default: switch case)
My issue is that I am trying to create a Opengl/Win32 application and I am unable to keep my dialog box open. It literally flashes as if someone pressed cancel on it RIGHT when it opened.
I've looked around google and found a few others with this issue, but none of the solutions they posted have helped me, so I turn to the StackOverflow community!
Initially, I wrote code for the Dialog Procedure...
LRESULT CALLBACK LoginDlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
ShowWindow(hWndDlg, SW_SHOW); // These were added to get the window to show up
UpdateWindow(hWndDlg); // even if the chance was small.
switch(Msg)
{
case WM_INITDIALOG:
return true;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
EndDialog(hWndDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
I then wrote the actual code to display the box.
void DisplayLoginBox()
{
LoginDlgHwnd = NULL;
LoginDlgHwnd = (HWND)DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(LOGIN_DIALOG),
app.GetHandle(),
reinterpret_cast<DLGPROC>(LoginDlgProc)
);
if(LoginDlgHwnd == NULL)
MessageBox(NULL, NULL, NULL, MB_OK);
}
app.GetHandle() returns a hwnd of the main program. This function works properly. and LoginDlgHwnd is a global variable.
The actual dialog is created and included properly as well. Do you have any ideas?
-Celestialkey
DialogBox does not return a hwnd, the function does not return until the dialog is closed, if you want a modeless dialog and a handle, use CreateDialog
The DLGPROC DialogBox parameter should not require a cast, change LoginDlgProc' LRESULT to INT_PTR
MessageBox(NULL, NULL, NULL, MB_OK); will not display anything, it needs text in the 2nd parameter
It is hard to say why the dialog does not stay open, but you should check the return value of DialogBox, if it is 0, the parent hwnd is invalid, if it is -1, call GetLastError() to get more info. One thing you could try is to remove all controls in the LOGIN_DIALOG dialog template (If you used common controls, but did not call InitCommonControls, the dialog would not work etc)