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)
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.
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 \""));
In my Win32 CPP program, I have defined some Child Window to display various text strings using something like:
hnd_to_this_ch_window = CreateWindow(
L"EDIT",L"Some initial text", WS_VISIBLE | WS_CHILD | ES_LEFT,
position_of_this_window_X,
position_of_this_window_Y,
TEXTOUT_DEFAULT_WIDTH,
TEXTOUT_DEFAULT_HEIGHT,
handle_to_my_parent_window, NULL,
hinstance_variable_used_by_create_window,
NULL )
My problem is that if I click with my mouse to select the text in one of such child windows (to, say, copy it somewhere), the focus of the application goes to this child window and so any keypresses which used to be handled through my main windows CALLBACK (with case WM_KEYDOWN:) are now captured into the child window, where they appear as inputted characters. What magic function do I call to have the focus go back to the parent (so that my WM_KEYDOWN) can work again? I was hoping I could just click on the main Window's title bar and that would take it back to normal, but that isn't working (because, obviously, my program is lacking some extra logic).
Handle the WM_KILLFOCUS message in the window procedure of the window you want to focus, and restore the focus using the SetFocus function.
If you want to focus the window when it is clicked, handle the WM_LBUTTONDOWN message.
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// Restore the focus when it was lost.
if (Msg == WM_KILLFOCUS) {
SetFocus(hWnd);
// Msg was handled, return zero.
return 0;
}
// Or when the window is clicked.
if (Msg == WM_LBUTTONDOWN) {
SetFocus(hWnd);
// Msg was handled, return zero.
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
case WM_KEYDOWN:
SetFocus(Parent_Hwnd);
return SendMessage(Parent_Hwnd,WM_KEYDOWN,wParam,lParam);
I am having issues with creating a modeless dialog from a DLL file. My dialog has nothing special on it, just an OK button and an edit box. I have looked at this Microsoft KB Article (http://support.microsoft.com/kb/233263) and have implemented its solution to create a window hook to grab and process messages.
The method provided by Microsoft solves the tab key problem, however, it creates another problem. When I type into the edit box on the dialog, whatever I press is duplicated 4 times. For example, if I press 'a' on the keyboard, 'aaaa' will show up in the edit box.
If I disable the Window Hook, then the edit box works correctly and only displays one 'a'.
What do I need to do to the Window Hook procedure to solve this problem?
Any help is greatly appreciated.
- - EDIT - -
As per request, my Window Hook Procedure Code: (It's the same as the KB article)
LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
LPMSG lpMsg = (LPMSG) lParam;
if (nCode >= 0 && PM_REMOVE == wParam) {
// Don't translate non-input events.
if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST)) {
if (IsDialogMessage(hwndDllDlg, lpMsg)) {
// The value returned from this hookproc is ignored,
// and it cannot be used to tell Windows the message has been handled.
// To avoid further processing, convert the message to WM_NULL
// before returning.
lpMsg->message = WM_NULL;
lpMsg->lParam = 0;
lpMsg->wParam = 0;
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
My Dialog Callback Procedure:
BOOL CALLBACK DllDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
DestroyWindow(hwndDlg);
hwndDllDlg = NULL;
}
return TRUE;
case WM_DESTROY:
UnhookWindowsHookEx(hHook);
return FALSE;
}
return FALSE;
}
}
Both hHook and hwndDllDlg are defined as HHOOK and HWND respectively.
HHOOK hHook;
HWND hwndDllDlg = CreateDialog(0, MAKEINTRESOURCE(DLG_MAIN), 0, DllDlgProc);
I looked at the KB article. It sounds reasonable. There is some point where you was not enough accurate while following the instructions from KB. Post your code. This may help.
If you have control over the message pump of the executable and can add IsDialogMessage there, then you do not need any hook. Code from the dll is part of the code of the process. Window handles are in the common space either.
Other approach is starting your own UI thread. If you create your dialog on this thread, then you will have your own message pump. The hook will not be needed in this case either.
Well, this is more of a question to author of the post..
I have the tab key issue and am trying to understand the microsoft article better.
So my dialog is shipped out as Dll and the application which I don't have access to is launching dialog from my dll.
HWND hwndDllDlg = CreateDialog(0, MAKEINTRESOURCE(DLG_MAIN), 0, DllDlgProc);
I don't understand what dialog the code refers to when they said hwndDllDlg in the article. Should I point my dialog creation to this variable ?
I'm at a loss on this one, not really even sure what code to post.
I have a c++ application. The initial window has an edit control, custom control, and menu. When the user presses F5, a new window open with its own message loop. The new window then opens a DialogBox, and is modal as expected.
The odd part is that the DialogBox seems to be hidden behind the 2nd window. I have to alt-tab to the first window, then alt-tab back to the second window to get to the dialog box.
If I cancel out of the DialogBox, the second window is destroyed (as expected), and a MessageBox is shown (as expected), but that message box seems to be hidden behind the first window. Again, I have to alt-tab twice to get the MessageBox to the forefront, and OK out of it.
Does anyone have any ideas what could cause this odd Pop-Under behavior with both the DialogBox and MessageBox?
Thanks!
Code to create the Dialog Box
INT_PTR ip = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_AMBIGUOUS), this->hWnd, DlgAmbiguous);
Code for the DlgAmbiguous Proceduels
INT_PTR CALLBACK DlgAmbiguous(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
HWND hStaticTerm = GetDlgItem(hDlg, IDC_TERM);
SetWindowText(hStaticTerm, lpAmbiguousTerm);
if (wcscmp(lpAmbiguousTerm, L"canvas") == 0)
{
HWND hComboBox = GetDlgItem(hDlg, IDC_MEANING);
SendMessage(hComboBox, CB_ADDSTRING, NULL, reinterpret_cast<LPARAM>(_T("Program Window")));
SendMessage(hComboBox, CB_ADDSTRING, NULL, reinterpret_cast<LPARAM>(_T("Region in Program Window")));
}
return (INT_PTR)TRUE;
}
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
HWND hComboBox = GetDlgItem(hDlg, IDC_MEANING);
iAmbiguousResult = SendMessage(hComboBox, CB_GETCURSEL, NULL, NULL);
EndDialog(hDlg, iAmbiguousResult + 100);
return (iAmbiguousResult == -1) ? FALSE : TRUE;
}
else if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, DLG_CANCEL);
return (INT_PTR)FALSE;
}
break;
}
return (INT_PTR)FALSE;
When you open a window, regardless if it runs on the same thread or not, it makes sense to specify its parent window. This will force new window to appear above its parent. The same applies to the dialog box:
INT_PTR WINAPI DialogBox(
_In_opt_ HINSTANCE hInstance,
_In_ LPCTSTR lpTemplate,
_In_opt_ HWND hWndParent,
_In_opt_ DLGPROC lpDialogFunc
);
Note the third parameter. Other option to bring your window on top is by calling the SetWindowPos function.