'WndClassEx.style = WS_OVERLAPPEDWINDOW' Not Registering - c++

In the following code I have a WindowClass, which is a class that wraps the WNDCLASS struct,
I've come to an issue where when I change the value of the 'style' member, the class does not
register, all help is appreciated!
(Edit- as It's 5 am for me, my apologies if I'm making a simple mistake)
class WindowClass
{
public:
WindowClass(LPCWSTR lpszClassNameIn, HINSTANCE hInstanceIn = NULL, WNDPROC lpfnWndProcIn = DefaultWindowProcedure)
{
WndClassEx.cbSize = sizeof(WndClassEx);
WndClassEx.lpszClassName = lpszClassNameIn;
WndClassEx.hInstance = hInstanceIn;
WndClassEx.lpfnWndProc = lpfnWndProcIn;
WndClassEx.style = WS_OVERLAPPEDWINDOW; // <-- This Causes The Class To Fail Registration
}
VOID Register()
{
if (!RegisterClassEx(&WndClassEx))
{
throwError(L"Failure To Register Class");
}
}
private:
WNDCLASSEX WndClassEx = { 0 };
};

Related

Minimalist CreateWindowEx fails

this is just a minimalist console application that should show a windows created on the fly :
#include <windows.h>
void main()
{
WNDCLASSEX _c4w = {0};
_c4w.cbSize = sizeof(WNDCLASSEX);
//_c4w.hCursor = ::LoadCursor(0, IDC_APPLICATION);
//_c4w.hIcon = ::LoadIcon(0, IDI_APPLICATION);
_c4w.hInstance = 0;
_c4w.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
_c4w.lpszClassName = "c4w";
HWND _h;
if(!::RegisterClassEx(&_c4w))
{ _h = ::CreateWindowEx( 0, "c4w",
"Minimal Windows Application",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480,
HWND_DESKTOP,
0,
::GetModuleHandle(0), NULL
);
::ShowWindow(_h, SW_SHOW);
}
....
}
unfortunatlity the RegisterClassEx function actually always fails...
I am using C++ Builder 5 and compiling a console Application optioned as MultiThreaded but no VCL...
As #WhozCraig said Your window class doesn't have a wndproc. If you want to use winapi well, please study according to the official documentation. Your program needs a wndproc.
Here is how to create a blank window in MSDN.
Notice that the program does not explicitly call the WindowProc
function, even though we said this is where most of the application
logic is defined. Windows communicates with your program by passing it
a series of messages.
In the code, wc.lpfnWndProc = WindowProc specifies the process callback function.
I understood that a normal Win32 application using HWND and WNDPROC is not what I have done, but here is my solution :
HWND GetSTD()
{ static
HWND _result(0);
static
bool _lock(false);
static
bool _setup(false);
while(_lock) ::Sleep(0);
if(_setup == false)
{ _lock = true;
OSVERSIONINFO _os;
_os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
::GetVersionEx(&_os);
if(_os.dwPlatformId != VER_PLATFORM_WIN32s)
{ char _title[1024];
::GetConsoleTitle(_title, sizeof(_title));
_result = ::FindWindow(0, _title);
if(_os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{ _result = ::GetWindow(_result, GW_CHILD);
if(_result != 0)
{ char _class[128];
::GetClassName(_result, _class, sizeof(_class));
while(::strcmp(_class, "ttyGrab") != 0)
{ _result = ::GetNextWindow(_result, GW_HWNDNEXT);
if(_result != 0)
::GetClassName(_result, _class, sizeof(_class));
}
}
}
}
_setup = true;
_lock = false;
}
return _result;
}
Using the resulting HWND, we could draw over the console with the ::GetDC() and ::ReleaseDC() mechanism...
NB : static variables are used to ensure to return only 1 STD handle per call...

Weird array behavior in classes along with Windows DCs (C++)?

I'm working on creating a text based Windows game, and I am having a problem (I guess) with arrays not working the same within a class scope as within the main function. As far as I can tell it is some kind of interaction between a larger array class member (or large total amount of variables) and Windows creating a DC or other Windows API calls and/or variables.
What I want to do is a have a class called Map that contains a two dimensional array of Tiles. Tile is just a simple struct with basic tile information. I would like to make the array 256 x 256. This shouldn't be a problem as far as I can figure. Each Tile should be 32 bytes. That's 2 MB total for the array.
However, the game crashes when I declare a variable of the Map class in the main function, and then do things with Windows DCs. The return value seems to vary, In the current form, it usually returns 255, but I have also gotten "process terminated with status -1073741571". A 128 x 128 array does work in the class though. It also works fine if I remove either the array or the code in DisplayScreen. And as I implied, it also works if I just move the array of Tiles to the main function.
I'm honestly baffled. I have no idea what the difference would be. Nothing is going out of scope. Doesn't matter if it is a public or private member. Non dynamic class members should all get declared on the stack and it shouldn't work any differently in a class versus otherwise, right?
For other information, I am using Code::Blocks with the Min GW compiler. Everything is up to date. I am running Windows 10. My computer specs shouldn't be an issue either, but if it matters, I have 16 GB memory and a 4Ghz Athlon FX 8 core processor.
Edit: Here is the full code, so nothing is left out
Game.h:
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
struct Tile
{
char chr[2];
int r[2], b[2], g[2];
bool solid;
bool translucent;
int opacity;
};
class Map
{
Tile tileMap[256][256];
public:
Map();
};
Map::Map()
{
int i, j;
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
tileMap[i][j].chr[0] = 'X';
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
tileMap[i][j].chr[1] = ' ';
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
main.cpp:
#include <windows.h>
#include "Game.h"
#define FRAMERATE 60
//Function declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void DisplayScreen(HWND pWnd, Map &pMap);
//Make the class name into a global variable
char strClassName[ ] = "GameApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrArgument,
int nCmdShow)
{
HWND hWnd; //This is the handle for our window
MSG messages; //Here messages to the application are saved
WNDCLASSEX wndClassEx; //Data structure for the windowclass
Map test;
DWORD sysTimer;
DWORD sysPrevTime = 0;
DWORD timerDelta = 1000 / FRAMERATE;
//Get a handle for the whole screen
HDC hDC = GetDC(NULL);
//Initalize the Window structure
wndClassEx.hInstance = hThisInstance;
wndClassEx.lpszClassName = strClassName;
wndClassEx.lpfnWndProc = WindowProcedure;
wndClassEx.style = CS_DBLCLKS;
wndClassEx.cbSize = sizeof (WNDCLASSEX);
wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClassEx.lpszMenuName = NULL; //No menu
wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hbrBackground = CreateSolidBrush(RGB(0,0,0));
//Register the window class, and if it fails quit the program
if (!RegisterClassEx (&wndClassEx))
return 0;
//Create Window with registered window class
hWnd = CreateWindowEx (
0,
strClassName, //Class name
"Game Test", //Title Text
WS_OVERLAPPEDWINDOW, //default window type
0, //X pos of window at top left
0, //Y pos of window at top left
GetDeviceCaps(hDC, HORZRES), //Set window width to screen width
GetDeviceCaps(hDC, VERTRES), //Set window height to screen height
HWND_DESKTOP, //Child-window to desktop
NULL, //No menu
hThisInstance, //Program Instance handler
NULL); //No Window Creation data
//Removes borders from the window
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
//Make the window visible on the screen
ShowWindow (hWnd, nCmdShow);
//Run the message and game loop
while (true)
{
while(PeekMessage(&messages,NULL,0,0, PM_REMOVE))
{
if (messages.message == WM_QUIT)
{
ReleaseDC(NULL, hDC);
DestroyWindow(hWnd);
return 0;
}
TranslateMessage(&messages);
DispatchMessage(&messages);
}
sysTimer = timeGetTime();
if (sysTimer >= (sysPrevTime + timerDelta) )
{
sysPrevTime = sysTimer;
DisplayScreen(hWnd, test);
}
}
}
//This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0); //Send WM_QUIT to the message queue
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return 0;
}
void DisplayScreen(HWND pWnd, Map &pMap)
{
HDC hDC = GetWindowDC(pWnd);
HDC hdcBuf = CreateCompatibleDC(hDC);
HBITMAP hbmBuf = CreateCompatibleBitmap(hDC, 800, 600);
HFONT hMapFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
HFONT hTxtFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
SelectObject(hdcBuf, hbmBuf);
SelectObject(hdcBuf, hMapFont);
SetBkColor(hdcBuf, RGB(0,0,0));
SetTextColor(hdcBuf, RGB(255,255,255));
//Draw to the buffer
TextOut(hdcBuf, 10, 10, "Hello World #", 15);
//Tranfers the buffer to the Screen
BitBlt(hDC, 100, 100, 800, 600, hdcBuf, 0, 0, SRCCOPY);
//Release all object handles
DeleteObject(hTxtFont);
DeleteObject(hMapFont);
DeleteObject(hbmBuf);
DeleteDC(hdcBuf);
ReleaseDC(pWnd, hDC);
}
It crashes with even one instance of something creating a DC. It works fine otherwise creating and destroying the DCs and displaying the bitmap over and over again even if I leave it for an hour. Once I create that class with the large array in it though, it just dies.
I actually used to have the Display function as a class function and I moved it out because I thought that was the problem, but it wasn't.
Interestingly, if I change the declaration from 'Map test;' to 'Map* test = new Map;' and change the rest of the program appropriately, it works. Honestly though, doing that just seems kind of dumb, and I think that would slow everything down if I don't have a good reason to put everything on the heap. Plus, I don't like bandages. If there is a problem I'd rather fix it.
Any ideas?
You have a stack overflow (the condition, not the website).
The problem can be reproduced in this program:
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Map test;
return 0;
}
It fails because it reaches stack limit.
Also tileMap[i][j].chr[2] is out of bound. It is declared as char chr[2]; valid index is 0 and 1. It can only go up to tileMap[i][j].chr[1]
Ditto b[], r[], and g[]
Change the Map class so that it allocates memory on heap and fix chr:
class Map
{
//Tile tileMap[256][256];
Tile **tileMap;
public:
Map();
~Map();
};
Map::Map()
{
int i, j;
tileMap = new Tile*[256];
for (i = 0; i < 256; i++)
tileMap[i] = new Tile[256];
for (i = 0; i<256; i++)
{
for (j = 0; j<256; j++)
{
//tileMap[i][j].chr[1] = 'X';
tileMap[i][j].chr[0] = 'X'; //<== meant to be 0?
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;
//tileMap[i][j].chr[2] = ' ';
tileMap[i][j].chr[1] = ' '; //<== meant to be 1?
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;
tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}
Map::~Map()
{
int i = 0;
for (i = 0; i < 256; i++)
delete[]tileMap[i];
delete[]tileMap;
}

DirectX 11: Runtime crash when running simple DirectX application

I've attempted to inherit some public globals from a base class and successfully got the window up and running and initialized directx similarly in a simple way- in it's own class, inheriting globals, such as HWND hWnd.
However when the program is run, D3D11CreateDeviceAndSwapChain() fails. On further inspection, debugger gives:
DXGI ERROR: IDXGIFactory::CreateSwapChain: No target window specified in DXGI_SWAP_CHAIN_DESC, and no window associated with owning factory. [ MISCELLANEOUS ERROR #6: ]
The DXGI_SWAP_CHAIN_DESC structure is as follows:
SwapChainDesc.BufferCount = 1;
SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.Width = 1024;
SwapChainDesc.BufferDesc.Height = 768;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.OutputWindow = hWnd;
SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.SampleDesc.Count = 4;
SwapChainDesc.Windowed = TRUE;
SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
Where hWnd is stored in:
class Infinity{
public:
Infinity();
~Infinity();
HWND hWnd;
};
And inherited as such:
class Direct3D : public Infinity{
public:
Direct3D();
~Direct3D();
IDXGISwapChain *Swapchain; //Display modes.
ID3D11Device *Device;
ID3D11DeviceContext *DeviceContext;
ID3D11RenderTargetView *RenderTargetView;
void D3D_Start(int width, int height);
void D3D_Render();
void D3D_Terminate();
}Direct3D;
Checked the value for SwapChainDesc.OutputWindow = hWnd; at runtime and it's null. (0x00000000) and I think that's what is causing Swapchain->GetBuffer to fail, since D3D11CreateDeviceAndSwapChain needs a working HWND. If this is true, Why is ShowWindow() successful?
Edit: I should also add that ShowWindow()is in a similar class inheriting from class Infinity:
class Windows : public Infinity{
public:
Windows();
~Windows();
bool DisplayWindow(int width, int height, HINSTANCE hInstance);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
}Windows;
Observe the following code:
class A {
public:
int memA;
static int memB;
};
int A::memB = 0;
class B : public A {};
class C : public A {};
int main() {
A a;
B b;
C c;
a.memA = 4;
b.memA = 5;
c.memA = 6;
A::memB = 4;
B::memB = 5;
C::memB = 6;
printf("a.memA = %d\n", a.memA);
printf("b.memA = %d\n", b.memA);
printf("c.memA = %d\n", c.memA);
printf("A::memB = %d\n", A::memB);
printf("B::memB = %d\n", B::memB);
printf("C::memB = %d\n", C::memB);
return 0;
}
The output of this code is:
a.memA = 4
b.memA = 5
c.memA = 6
A::memB = 6
B::memB = 6
C::memB = 6
By making a member static, you ensure that: A) There is only ever one instance of that member and B) All child classes have direct access to that member (assuming it isn't private). Your hWnd is not global as your code is written, however making it static will accomplish what you want.
The following code does this:
//header file
class Infinity {
public:
static HWND hWnd;
};
//cpp file
HWND Infinity::hWnd = NULL;
Your Direct3D class will be able to access the non-null hWnd written to by your Window class. This is only a valid solution if you intend to create one window - otherwise, you will have to resort to a more complicated parent-child relationship between the two classes (probably without using inheritance).

C++ - WINAPI - Possible conflict with std::map?

While trying to find a suitable solution to handling window messages, I came across this question here on StackOverflow:
Object oriented c++ win32?
The answers offered great solutions and my personal favourite is the accepted answer using std::map.
However, whenever I use std::map in my code that looks like this:
#include <cstdio>
#include <map>
#include <windows.h>
#include <helixirrwidgets/Window.hpp>
using namespace HelixirrWidgets;
/// ----------------------------
/// #class Window
/// #brief Represents a window.
/// ----------------------------
/// Inner classes:
class Window::Helper{
public:
/// Constructors & destructors:
Helper(void) : active(false), created_window(false), handle_instance(GetModuleHandle(NULL)), handle_window(nullptr), message({0}){
_ms_mopopHelpers.insert({handle_window, this});
}
Helper(Helper const& helper_) : active(false), created_window(false), handle_instance(helper_.handle_instance), handle_window(helper_.handle_window), message(helper_.message){
_ms_mopopHelpers.insert({handle_window, this});
}
Helper(Helper&& helper_) : active(false), created_window(false), handle_instance(std::move(helper_.handle_instance)), handle_window(std::move(helper_.handle_window)), message(std::move(helper_.message)){
helper_.handle_instance = nullptr;
helper_.handle_window = nullptr;
_ms_mopopHelpers.insert({handle_window, this});
}
~Helper(void){
handle_instance = nullptr;
handle_window = nullptr;
_ms_mopopHelpers.erase(handle_window);
}
/// Member data:
bool mutable active, created_window;
HINSTANCE mutable handle_instance;
HWND mutable handle_window;
MSG message;
/// Member functions (overloaded operators, assignment):
Helper& operator=(Helper const& helper_) = default;
Helper& operator=(Helper&& helper_) = default;
/// Static member functions:
static LRESULT CALLBACK handle_callback(HWND handle_window_, UINT message_, WPARAM wparam_, LPARAM lparam_){
if(_ms_mopopHelpers.size() != 0){
// Delegate message handling:
return _ms_mopopHelpers[handle_window_]->_handle_callback(message_, wparam_, lparam_);
}
return 0;
}
private:
/// Member functions:
LRESULT _handle_callback(UINT message_, WPARAM wparam_, LPARAM lparam_){
switch(message_){
case WM_DESTROY:
active = false;
DestroyWindow(handle_window);
return 0;
default:
return DefWindowProc(handle_window, message_, wparam_, lparam_);
}
}
/// Static member data:
static std::map<HWND, Window::Helper*> _ms_mopopHelpers;
};
/// Static member data:
std::map<HWND, Window::Helper*> Window::Helper::_ms_mopopHelpers = {};
/// Constructors & destructors:
Window::Window(void) : _m_bVisible(false), _m_opHelper(new Window::Helper){
}
Window::Window(Window const& window_) = default;
Window::Window(Window&& window_) = default;
Window::Window(std::string const& name_) : _m_bVisible(false), _m_opHelper(new Window::Helper), _m_oName(name_){
}
Window::Window(std::string&& name_) : _m_bVisible(false), _m_opHelper(new Window::Helper), _m_oName(std::move(name_)){
}
Window::~Window(void) = default;
/// Member functions:
bool const& Window::active(void) const noexcept{
return _m_opHelper->active;
}
Window& Window::save_changes(void){
// Create and register window class:
static bool __registered_class_window = false;
static WNDCLASSEX __class_window = {
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW,
Window::Helper::handle_callback,
0, 0,
_m_opHelper->handle_instance,
LoadIcon(_m_opHelper->handle_instance, NULL),
LoadCursor(NULL, IDC_ARROW),
reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
NULL,
"Helixirr Widgets Window Class Basic",
LoadIcon(_m_opHelper->handle_instance, NULL)
};
if(!__registered_class_window){
RegisterClassEx(&__class_window);
__registered_class_window = true;
}
// If window hasn't been created yet:
if(!_m_opHelper->created_window){
_m_opHelper->created_window = true;
_m_opHelper->handle_window = CreateWindowEx(
0,
"Helixirr Widgets Window Class Basic",
_m_oName.c_str(),
WS_OVERLAPPEDWINDOW,
_m_uiPos[0], _m_uiPos[1],
_m_uiSize[0], _m_uiSize[1],
NULL, NULL, _m_opHelper->handle_instance, NULL
);
}
_m_opHelper->active = true;
return *this;
}
void Window::show(void){
if(_m_opHelper->active){
if(GetMessage(&_m_opHelper->message, NULL, 0, 0)){
// Handle messages:
TranslateMessage(&_m_opHelper->message);
DispatchMessage(&_m_opHelper->message);
// Handle window displaying:
ShowWindow(_m_opHelper->handle_window, SW_SHOWDEFAULT);
UpdateWindow(_m_opHelper->handle_window);
return;
}
}
}
my window doesn't open for some reason. After cutting way all connections to std::map, window shows up again just fine. What might be causing this wierd phenomenon? It is quite hard to believe there's some kind of conflict.
Judging from your Window::show method, the problem might be that you don't have a message loop. A normal message loop looks like this:
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
But your Window::show method only does this once, so the window might not get pumped the messages needed to actually display the window.

C++ Win32 Error [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I made a class for Win32 and I have no idea why this error happens.
This is the code:
main.cpp
using namespace std;
#include "WindowManager.h"
#define WIDTH 700
#define HEIGHT 500
#define VERSION 0.1
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreviousInstance,LPSTR lpcmdline,int nCmdShow)
{
WindowManager window("TalkToMe", 100, 100, WIDTH, HEIGHT);
while(window.isWindowOpen())
{
window.PekMessage();
}
return 0;
}
WindowManager.h
#pragma once
#include <Windows.h>
class WindowManager
{
private:
MSG msg;
HWND window;
int stat;
public:
WindowManager(LPCTSTR title,int x, int y, int width, int height);
~WindowManager();
LRESULT CALLBACK WindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2);
inline bool isWindowOpen() { return stat != -1; }
int getStat() { return stat; }
void PekMessage();
};
WindowManager.cpp
#include "WindowManager.h"
void WindowManager::PekMessage()
{
if(PeekMessage(&msg, window, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
LRESULT CALLBACK WindowManager::WindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
{
switch(uint_Message)
{
case 16: // exit button
stat = -1;
break;
}
return DefWindowProc(winhan,uint_Message,parameter1,parameter2);
}
WindowManager::WindowManager(LPCTSTR title,int x, int y, int width, int height)
{
stat = 0;
WNDCLASSEX wnd;
wnd.cbSize = sizeof(wnd);
wnd.style = CS_HREDRAW | CS_VREDRAW;
wnd.lpfnWndProc = WindowProcedure;
wnd.cbClsExtra = 0;
wnd.cbWndExtra = 0;
wnd.hInstance = GetModuleHandle(NULL);
wnd.hIcon = NULL;
wnd.hCursor = LoadCursor(NULL,IDC_ARROW);
wnd.hbrBackground = GetSysColorBrush(NULL);
wnd.lpszClassName = "TalkToMe";
wnd.lpszMenuName = NULL;
wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wnd);
window = CreateWindowEx(WS_EX_CONTROLPARENT, wnd.lpszClassName, title,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, x, y, width, height,NULL, NULL,
GetModuleHandle(NULL), NULL);
}
WindowManager::~WindowManager()
{
DestroyWindow(window);
}
This is the weird build failure:
1>------ Build started: Project: Client, Configuration: Debug Win32 ------
1> WindowManager.cpp
1>c:\users\user\documents\visual studio 2012\projects\talktome\talktome\windowmanager.cpp(31): error C3867: 'WindowManager::WindowProcedure': function call missing argument list; use '&WindowManager::WindowProcedure' to create a pointer to member
1>c:\users\user\documents\visual studio 2012\projects\talktome\talktome\windowmanager.cpp(31): error C2440: '=' : cannot convert from 'LRESULT (__stdcall WindowManager::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
1> There is no context in which this conversion is possible
1> Generating Code...
1> Compiling...
1> Main.cpp
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
This is to be expected. WindowManager::WindowManager has a hidden this argument, thus it does not respect the definition required for wnd.lpfnWndProc.
To work around this issue, you need to define a helper function as follows:
LRESULT CALLBACK HelperWindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
{
if (uint_Message == WM_CREATE)
{
/* Retrieve "this" sent through CreateWindowEx */
WindowManager *wm = (WindowManager *)(((LPCREATESTRUCT) lParam)->lpCreateParams);
/* And store it as window-private date */
SetWindowLongPtr(winhan, GWLP_USERDATA, wm);
}
/* Retrieve WindowManager from window-private data */
WindowManager *wm = (WindowManager *)GetWindowLongPtr(winhan, GWLP_USERDATA);
/* Forward window message to WindowManager */
wm->WindowProcedure(winhan, uint_Message, parameter1, parameter2);
}
WindowManager::WindowManager()
{
...
/* use helper window procedure */
wnd.lpfnWndProc = HelperWindowProcedure;
...
/* send "this" through WM_CREATE */
window = CreateWindowEx(WS_EX_CONTROLPARENT, wnd.lpszClassName, title,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, x, y, width, height,NULL, NULL,
GetModuleHandle(NULL), this);
}
As user1202136 mentioned, C++ class methods have implicit parameter that gets passed into the function whenever it is called. It holds the pointer to the class instance (this pointer) and allows you to access the class variables. In order to resolve this issue, you can make the WindowProcedure method static and use GWL_USERDATA within the window memory to store your class instance (this pointer). Look up GetWindowLongPtr for more information. When creating the window you'll need to pass this pointer via lpParam parameter, and store it using SetWindowLongPtr when you are handling WM_CREATE message.
check solutions:
wnd.lpfnWndProc = (WNDPROC)WindowProcedure;
or
LRESULT WNDPROC WindowManager::WindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)