Cameron P
Cameron P

Reputation: 57

WNDCLASSEX not taking WNDPROC parameter

trying to learn some WinAPI here and running into trouble passing a WNDPROC to my wcex.lpfnWndProc, it's all fine in the decleration but I get an error when I call MyWinClass(WNDPROC, LPCWSTR, HINSTANCE);

The error is in the WinMain function at the bottom of this code section.

The source I am learning from is dated 1998, but it has been the most intuitive(For me personaly), it have been replacing older versions such as WNDCLASS with the extended versions WNDCLASSEX, CreateWindowEx etc...

#include <Windows.h>
#include <string>
using namespace std;

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

class MyWinClass
{
public:
    MyWinClass(WNDPROC winProc, LPCWSTR className, HINSTANCE hInst);
    void Register()
    {
        ::RegisterClassEx(&wcex);
    }
private:
    WNDCLASSEX wcex;
};

MyWinClass::MyWinClass(WNDPROC winProc, LPCWSTR className, HINSTANCE hInst)
{
    wcex.style = 0;
    wcex.lpfnWndProc = winProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInst;
    wcex.hIcon = 0;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = 0;
    wcex.lpszClassName = className;
}

class CreateMyWindow
{
public:
    CreateMyWindow() : _hwnd(0){}
    CreateMyWindow(char const * caption, char const * className, HINSTANCE hInstance);
    void ShowWindow(int cmdShow)
    {
        ::ShowWindow(_hwnd, cmdShow);
        ::UpdateWindow(_hwnd);
    }
protected:
    HWND _hwnd;
};

CreateMyWindow::CreateMyWindow(char const * caption, char const * className, HINSTANCE hInstance)
{
    _hwnd = ::CreateWindowEx(
        (DWORD)className,
        (LPCWSTR)caption,
        WS_OVERLAPPED,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        0,
        0,
        NULL,
        hInstance,
        0);
}


//MyWindow Procedure that is called by windows

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
    char className[] = "Winnie";

    MyWinClass myWinClass(WindowProcedure, className, hInst);
    /*Error: no Instance of constructor "MYWinClass::MYWinClass" mat  the argument list argument types are:(LRESULT _stdcall(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) char[7], HINSTANCE)

//MyWinClass myWinClass(WindowProcedure...) us underlined with above error, and I do not know why it is seeing WNDPROC as an HWND.*/
    myWinClass.Register();

    CreateMyWindow myWndClass("MyWindowClass", className, hInst);
    myWndClass.ShowWindow(cmdShow);

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

Upvotes: 0

Views: 1122

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595329

You are mixing ANSI and Unicode data in incorrect ways, and some of your type-casts are wrong. Try something more like this instead:

#include <Windows.h>

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

class MyWinClass
{
public:
    MyWinClass(WNDPROC winProc, LPCTSTR className, HINSTANCE hInst);

    void Register()
    {
        ::RegisterClassEx(&wcex);
    }

private:
    WNDCLASSEX wcex;
};

MyWinClass::MyWinClass(WNDPROC winProc, LPCTSTR className, HINSTANCE hInst)
{
    wcex.style = 0;
    wcex.lpfnWndProc = winProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInst;
    wcex.hIcon = 0;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = 0;
    wcex.lpszClassName = className;
}

class CreateMyWindow
{
public:
    CreateMyWindow() : _hwnd(0){}
    CreateMyWindow(LPCTSTR caption, LPCTSTR className, HINSTANCE hInstance);

    void ShowWindow(int cmdShow)
    {
        ::ShowWindow(_hwnd, cmdShow);
        ::UpdateWindow(_hwnd);
    }

protected:
    HWND _hwnd;
};

CreateMyWindow::CreateMyWindow(LPCTSTR caption, LPCTSTR className, HINSTANCE hInstance)
{
    _hwnd = ::CreateWindowEx(
        0,
        className,
        caption,
        WS_OVERLAPPED,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);
}


//MyWindow Procedure that is called by windows

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
    TCHAR className[] = TEXT("Winnie");

    MyWinClass myWinClass(WindowProcedure, className, hInst);
    myWinClass.Register();

    CreateMyWindow myWndClass(TEXT("MyWindowClass"), className, hInst);
    myWndClass.ShowWindow(cmdShow);

    MSG msg;

    while (::GetMessage(&msg, NULL, 0, 0))
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return msg.wParam;
}

Or:

#include <Windows.h>

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

class MyWinClass
{
public:
    MyWinClass(WNDPROC winProc, LPCWSTR className, HINSTANCE hInst);

    void Register()
    {
        ::RegisterClassExW(&wcex);
    }

private:
    WNDCLASSEXW wcex;
};

MyWinClass::MyWinClass(WNDPROC winProc, LPCWSTR className, HINSTANCE hInst)
{
    wcex.style = 0;
    wcex.lpfnWndProc = winProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInst;
    wcex.hIcon = 0;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = 0;
    wcex.lpszClassName = className;
}

class CreateMyWindow
{
public:
    CreateMyWindow() : _hwnd(0){}
    CreateMyWindow(LPCWSTR caption, LPCWSTR className, HINSTANCE hInstance);

    void ShowWindow(int cmdShow)
    {
        ::ShowWindow(_hwnd, cmdShow);
        ::UpdateWindow(_hwnd);
    }

protected:
    HWND _hwnd;
};

CreateMyWindow::CreateMyWindow(LPCWSTR caption, LPCWSTR className, HINSTANCE hInstance)
{
    _hwnd = ::CreateWindowExW(
        0,
        className,
        caption,
        WS_OVERLAPPED,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);
}


//MyWindow Procedure that is called by windows

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow)
{
    WCHAR className[] = L"Winnie";

    MyWinClass myWinClass(WindowProcedure, className, hInst);
    myWinClass.Register();

    CreateMyWindow myWndClass(L"MyWindowClass", className, hInst);
    myWndClass.ShowWindow(cmdShow);

    MSG msg;

    while (::GetMessage(&msg, NULL, 0, 0))
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return msg.wParam;
}

Upvotes: 2

Benjamin Lindley
Benjamin Lindley

Reputation: 103693

The issue is not your window procedure. It is with className. Your constructor is defined to take LPCWSTR, a.k.a, wchar_t const*. But className is an array of char, not an array of wchar_t. You can fix this error by declaring it as:

wchar_t className[] = L"Winnie";

However, you have a myriad of of other problems with your code that I won't go into at this time.

Upvotes: 3

Related Questions