First time, I wanted to create modeless dialog and to show file explorer if clicking a button. But, using MAKEINRESOOURCE to create dialog caused error that all icons&buttons except file can't be focused.
Next, I tried to change method into popup or child window. Here is my code.
. . .
HINSTANCE hInst;
HWND _main_hWnd;
HWND _popup_hWnd;
HWND _popBtn;
. . .
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_LEARNAPIMDI, szWindowClass, MAX_LOADSTRING);
LoadStringW(hInstance, IDS_POPUPCLASS, szPopupWndClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
MyRegisterPopupClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
if (!PopupInstance(hInstance, 250, 200, 400, 200))
{
return FALSE;
}
. . .
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LEARNAPIMDI));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_LEARNAPIMDI);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
ATOM MyRegisterPopupClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = PopupProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LEARNAPIMDI));
wcex.hCursor = LoadCursor(nullptr, IDC_CROSS);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szPopupWndClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
_main_hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!_main_hWnd)
{
return FALSE;
}
ShowWindow(_main_hWnd, nCmdShow);
UpdateWindow(_main_hWnd);
return TRUE;
}
BOOL PopupInstance(HINSTANCE hInstance, int sx, int sy, int rw, int rh)
{
_popup_hWnd = CreateWindow(szPopupWndClass, szPopupWndClass, WS_POPUP | WS_VISIBLE |
WS_BORDER | WS_CAPTION, sx, sy, rw, rh, _main_hWnd, NULL, hInst, NULL);
if (!_popup_hWnd)
return FALSE;
_popBtn = CreateWindow(L"Button", L"123", WS_CHILD | WS_BORDER | WS_VISIBLE |
BS_PUSHBUTTON, 20, 20, 40, 20, _popup_hWnd, (HMENU)IDC_POP_BTN1, hInst, NULL);
return TRUE;
}
. . .
LRESULT CALLBACK PopupProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDC_POP_BTN1:
{
TCHAR fillName[MAX_PATH] = {0,};
TCHAR dir[MAX_PATH] = { 0, };
_tgetcwd(dir, MAX_PATH);
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = L"BMP 파일\0*.bmp;*.BMP\0TEXT 파일\0*.txt;*.TXT\0DLDB 파일\0
*.dldb;*.DLDB\0";
ofn.nMaxFile = 256;
ofn.lpstrFile = fillName;
ofn.lpstrInitialDir = dir;
if (0 != GetOpenFileName(&ofn))
{
MessageBox(NULL, fillName, L"123", MB_OK);
}
}
break;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This works well. And...
/* MainWindow.h */
class MainWindow : public Singleton<MainWindow>
{
private:
HINSTANCE _hInst;
HWND _hWnd;
WCHAR _szTitle[MAX_LOADSTRING];
WCHAR _szWindowClass[MAX_LOADSTRING];
WCHAR _szChildDataSetClass[MAX_LOADSTRING];
HWND _child;
HWND _btnChild;
public:
MainWindow();
~MainWindow();
bool Initialize(HINSTANCE hInstance);
int Run();
LRESULT AppProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT ChildAppProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void ClassLoadString();
void MyResisterClass();
bool CreateSystemWindow(int sW, int sH);
void CreateChildWindow(HWND hWnd, WCHAR* sz, UINT id,
LRESULT(*Proc)(HWND, UINT, WPARAM, LPARAM), int x, int y, int sW, int sH);
void ResisterChild(WCHAR* sz, UINT id, LRESULT(*Proc)(HWND, UINT, WPARAM, LPARAM));
bool ChildInstantiate(HWND hWnd, WCHAR* sz, int x, int y, int sW, int sH);
};
/* MainWindow.cpp */
#include "framework.h"
#include "Resource.h"
#include "MainWindow.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return MainWindow::Instance()->AppProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return MainWindow::Instance()->ChildAppProc(hWnd, message, wParam, lParam);
}
MainWindow::MainWindow()
{
_hInst = NULL;
_hWnd = NULL;
_child = NULL;
memset(_szTitle, 0, MAX_LOADSTRING);
memset(_szWindowClass, 0, MAX_LOADSTRING);
}
MainWindow::~MainWindow()
{
}
bool MainWindow::Initialize(HINSTANCE hInstance)
{
_hInst = hInstance;
ClassLoadString();
MyResisterClass();
if (!CreateSystemWindow(800, 800))
{
MessageBox(NULL, L"Failed creating window.", L"Error", MB_OK);
return false;
}
if (!_child)
{
CreateChildWindow(_child, _szChildDataSetClass, IDC_TESTCHILD, ChildProc,
50, 50, 300, 400);
ShowWindow(_child, SW_SHOW);
}
return true;
}
int MainWindow::Run()
{
MSG msg;
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT MainWindow::AppProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT MainWindow::ChildAppProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
_btnChild = CreateWindow(L"Button", L"asd", BS_PUSHBUTTON | WS_CHILD | WS_BORDER | WS_VISIBLE,
20, 20, 75, 50, _child, (HMENU)IDC_CHILD_BTN1, _hInst, NULL);
MessageBox(NULL, L"asd", L"asd", MB_OK);
}
break;
case WM_DESTROY:
DestroyWindow(_child);
_child = NULL;
break;
case WM_CLOSE:
DestroyWindow(_child);
_child = NULL;
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void MainWindow::ClassLoadString()
{
LoadStringW(_hInst, IDS_APP_TITLE, _szTitle, MAX_LOADSTRING);
LoadStringW(_hInst, IDC_TESTCHILD, _szWindowClass, MAX_LOADSTRING);
}
void MainWindow::MyResisterClass()
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = _hInst;
wcex.hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_TESTCHILD));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTCHILD);
wcex.lpszClassName = _szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
}
bool MainWindow::CreateSystemWindow(int sW, int sH)
{
_hWnd = CreateWindowW(_szWindowClass, _szTitle, WS_OVERLAPPED | WS_CAPTION |
WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX, CW_USEDEFAULT,
0, sW, sH, nullptr, nullptr, _hInst, nullptr);
if (!_hWnd)
{
return FALSE;
}
ShowWindow(_hWnd, SW_SHOW);
UpdateWindow(_hWnd);
return true;
}
void MainWindow::CreateChildWindow(HWND hWnd, WCHAR* sz, UINT id,
LRESULT(*Proc)(HWND, UINT, WPARAM, LPARAM), int x, int y, int sW, int sH)
{
ResisterChild(sz, id, Proc);
if (!ChildInstantiate(hWnd, sz, x, y, sW, sH))
{
MessageBox(NULL, L"Failed creating window.", L"Error", MB_OK);
}
}
void MainWindow::ResisterChild(WCHAR* sz, UINT id,
LRESULT (*Proc)(HWND, UINT, WPARAM, LPARAM))
{
WNDCLASSEXW wcex;
LoadStringW(_hInst, id, sz, MAX_LOADSTRING);
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = Proc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = _hInst;
wcex.hIcon = LoadIcon(_hInst, MAKEINTRESOURCE(IDI_SMALL));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = sz;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
if (!RegisterClassExW(&wcex))
{
MessageBox(NULL, L"123", L"123", MB_OK);//////////////*****
}
}
bool MainWindow::ChildInstantiate(HWND hWnd, WCHAR* sz, int x, int y, int sW, int sH)
{
hWnd = CreateWindow(sz, L"Data Sets", WS_POPUP | WS_VISIBLE | WS_BORDER | WS_CAPTION,
x, y, sW, sH, _hWnd, NULL, _hInst, NULL);
if (!hWnd)
return FALSE;
return TRUE;
}
This does't work well. It seems to go wrong with ResisterChild beacause MessageBox I marked is pop up. But, why does a child window named Data Sets be displayed though ResisterChild failed? I think that parameters of the functions associated with child window are not appropriate...
(I ask for your understanding about my not fluent english.)
If we can't click main window to focus on while a modeless dialog is on, you may have to check the dialog Proc.
This code must be changed to...
This will help you by focusing properly. In my case, I couldn't click and focus main window or file explorer. Now, I can do that.