Reputation: 20746
Is there any way to get text from a dialog window created by DialogBox
other than a global variable?
I mean, this is how I do it at the moment:
wchar_t str[80];
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (GetDlgItemText(hDlg, IDC_EDIT, str, sizeof(str) / sizeof(*str)) == 0)
*str = 0;
EndDialog(hDlg, wParam);
return (INT_PTR)TRUE;
case IDCANCEL:
EndDialog(hDlg, wParam);
return (INT_PTR)TRUE;
}
}
return (INT_PTR)FALSE;
}
But I wonder if it's possible to get rid of that str
global variable?
Upvotes: 0
Views: 190
Reputation: 31599
You can create the dialog box with DialogBoxParam
which allows passing initialization data to the dialog.
In WM_INITDIALOG
, use SetWindowLongPtr
to save this data, then data is accessible in dialog procedure.
Note that with this method you are passing a pointer, therefore sizeof(ptr)/sizeof(*ptr)
is not going to return the right allocation size.
Ideally, you may want to declare local variable wchar_t *str = NULL;
and pass its address, then allow the dialog to allocate memory. The caller will then be responsible to free the memory.
INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_INITDIALOG:
SetWindowLongPtr(hwnd, GWL_USERDATA, lparam);
break;
case WM_COMMAND:
switch(LOWORD(wparam))
{
case IDOK:
{
wchar_t *str = (wchar_t*)GetWindowLongPtr(hwnd, GWL_USERDATA);
if(str)
GetDlgItemText(hwnd, IDC_EDIT1, str, 80);
EndDialog(hwnd, wparam);
return (INT_PTR)TRUE;
}
}
}
return (INT_PTR)FALSE;
}
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int)
{
wchar_t str[80];
if(IDOK == DialogBoxParam(hinst, MAKEINTRESOURCE(IDD_DIALOG1), 0,
DialogProc, (LPARAM)(&str)))
MessageBox(0, str, 0, 0);
return 0;
}
Upvotes: 1
Reputation: 7170
First, since lParam
hasn't been used, can you set lParam = (LPARAM )str
to save the address of str ?
Second, the return type isINT_PTR
, but you only use to return TURE/FALSE, why not return the pointer value instead of TRUE
(since the str pointer is always != NULL here):
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
wchar_t* str = new wchar_t[80];
if (!str) return (INT_PTR)FALSE;
if (GetDlgItemText(hDlg, IDC_EDIT, str, 80) == 0)
*str = 0;
EndDialog(hDlg, wParam);
return (INT_PTR)str;
case IDCANCEL:
EndDialog(hDlg, wParam);
return (INT_PTR)TRUE;
}
}
return (INT_PTR)FALSE;
}
Notes that, you'd better allocate memory for str in callback, so that the data won't be overwritten by others. You of course could also use any IPC method, but it will get more complicated.
Upvotes: 0