What should I do more for creating controls on popup window?

107 Views Asked by At

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.)

1

There are 1 best solutions below

0
Choi tofu On

If we can't click main window to focus on while a modeless dialog is on, you may have to check the dialog Proc.

INT_PTR DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_COMMAND:
        break;
        
        //and so on...
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

This code must be changed to...

INT_PTR DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        //codes...
    }
    return (INT_PTR)FALSE;
}

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.