无法从BaseWindow类C ++ Visual Studio执行多个派生类(无法创建多个窗口)

时间:2019-11-01 16:39:36

标签: c++ winapi window

早上好。

我正在使用Managing Application State中使用的BaseWindow类创建应用程序

一切正常,该应用程序是一个带有一些按钮和列表视图的单个窗口,现在我想添加另一个窗口以将其用作“报告”窗口,该窗口将通过菜单命令创建。

问题是报告窗口在HWND中返回0,该类被注册而没有任何问题,我使用了GetLastError(),返回值为0(“一切正常”)。永远不会创建报告窗口。

这是对我所做工作的快速回顾:

  1. BaseClass<MainWindow>继承MainWindow并创建 MainWindow-好的
  2. BaseClass<ReportWindow>继承ReportWindow-确定
  3. ReportWindow是MainWindow的成员类-好的
  4. ReportWindow调用菜单上的创建命令-错误!,HWND为0, 没有得到     已创建

其他都可以,这是代码:

Main.cpp

// other not related code

MainWindow win;
char szTitle[MainWindow::nMaxLoadString];
LoadString(hInst, IDS_APPTITLE, szTitle, MainWindow::nMaxLoadString);

win.Create(szTitle, WS_OVERLAPPEDWINDOW, 0, CW_USEDEFAULT, CW_USEDEFAULT, 542, 343);
win.Show(SW_SHOWDEFAULT);

// other not related code

ReportWindow.h

#pragma once
#include "BaseWindow.h"

class ReportWindow : public BaseWindow<ReportWindow>
{
public:
    ReportWindow() : BaseWindow<ReportWindow>(){}
    LPCSTR ClassName() const override { return "AdminLockerRpt"; }
    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

private:
};

ReportWindow.cpp

#include "ReportWindow.h"

LRESULT ReportWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    }
    return 0;
}

MainWindow.h

#pragma once
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#include "BaseWindow.h"

#include "ReportWindow.h"

class MainWindow : public BaseWindow<MainWindow>
{
public:
    MainWindow();

public:
    LPCSTR ClassName() const override { return szClassName; }
    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

// other not related code

Private:
    ReportWindow rpt;

// other not related code

};

MainWindow.cpp

#pragma once
#include "MainWindow.h"

MainWindow::MainWindow() 
    : BaseWindow<MainWindow>() 
{
// other not related code
}

LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
    {
        // other not related code
    }
    break;
    case WM_COMMAND:
        if(HIWORD(wParam) == BN_CLICKED)
            // other not related code

// Here is the error, rpt.Create() returns 0, as its HWND is 0
// I use GetLastError() inmediately after this and I get 0 as return value
// I also tried to get the last error at the BaseWindow class, with the same results
// I only get error 1401 if I use a number as the HMENU parameter of the Create function
// ReportWindow doesn't get created :(

                        rpt.Create("Report", WS_OVERLAPPEDWINDOW);
                        DWORD dwLastError = GetLastError(); // returns 0, "Everything is ok"
                        rpt.Show(SW_SHOWDEFAULT);

        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    return 0;
}

我希望您能对此有所帮助。预先感谢您的宝贵时间!

以防万一,我包括了BaseWindow类的代码:

BaseWindow.h

#pragma once
#include "stdafx.h"
#include "Resource.h"
#include <cassert>

template <class DERIVED_T>
class BaseWindow
{
public:
    BaseWindow() : hWnd(nullptr), hInst(GetModuleHandle(nullptr)), wcx({0}) {}

    BOOL Create(LPCSTR lpWindowName, DWORD dwStyle, DWORD dwExStyle = 0,
        int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int width_in = CW_USEDEFAULT, int height_in = CW_USEDEFAULT,
        HWND hWndParent = nullptr, HMENU hMenu = nullptr)
    {
        RECT wr = {0};
        wr.left = x;
        wr.right = width_in + x;
        wr.top = y;
        wr.bottom = height_in + y;
        AdjustWindowRect(&wr, dwStyle, TRUE);

        width = wr.right - wr.left;
        height = wr.bottom - wr.top;

        wcx.cbSize = sizeof(wcx);
        wcx.hInstance = hInst;
        wcx.lpszClassName = ClassName();
        wcx.lpfnWndProc = DERIVED_T::WndProc;
        wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wcx.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wcx.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAINICON));

        ATOM aResult = RegisterClassEx(&wcx);
        assert(aResult != 0);

        hWnd = CreateWindowEx(
            dwExStyle, ClassName(), lpWindowName, dwStyle,
            x, y, width, height,
            hWndParent, hMenu, hInst, this
        );

        assert(hWnd != 0);

        return (hWnd ? TRUE : FALSE);
    }
    void Show(int nCmdShow) { ShowWindow(hWnd, nCmdShow); }
    HWND Window() const { return hWnd; }

protected:
    virtual LPCSTR ClassName() const = 0;
    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;

public:
    static constexpr int nMaxLoadString = 100;

protected:
    HWND hWnd;
    HINSTANCE hInst;
    char szClassName[nMaxLoadString];
    int width;
    int height;
    WNDCLASSEX wcx;

public:
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        DERIVED_T* pThis = nullptr;

        if (uMsg == WM_NCCREATE)
        {
            CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
            pThis = (DERIVED_T*)pCreate->lpCreateParams;
            SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pThis);

            pThis->hWnd = hWnd;
        }
        else
        {
            pThis = (DERIVED_T*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
        }
        if (pThis)
        {
            return pThis->HandleMessage(uMsg, wParam, lParam);
        }
        else
        {
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }

    }
};

0 个答案:

没有答案