Hello everyone,
I am making a VC++ 2008 project in pure Win32 API which uses common controls. Now the problem that I am facing is if I explicitly link to the comctl32.dll(version 6.0.) in the WinSXS folder using the LoadLibrary API function, my main window does not even display. But if I use the #pragma comment in my code as such -:
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
and add the comctl32.lib to my project dependencies then run it then I get my expected output. But if I link manually to the comctl32.dll in the WinSXS using LoadLibrary API function and then get the procedure address of InitCommonControls using the GetProcAddress Api function and then call it my main window does not even display. Why is this happening?
By definition I should be able to load my dll manually locate the required procedure that I want to use and execute it, but for some reason this is not happening here.
this is the code that I am using -:
#include <Windows.h>
#include <CommCtrl.h>
#include "resource.h"
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogFunc(HWND, UINT, WPARAM, LPARAM);
char szWinName[]="Timer Main Window";
HWND hDlg=NULL;
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
LPSTR lpszArgs, int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
HMODULE hmod=NULL;
void (*InitCommonControls)(void)=NULL;
wndclass.cbSize=sizeof(WNDCLASSEX);
wndclass.hInstance=hThisInst;
wndclass.lpszClassName=szWinName;
wndclass.lpfnWndProc=WindowFunc;
wndclass.style=0;
wndclass.hIcon=LoadIcon(hThisInst,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hIconSm=LoadIcon(hThisInst,MAKEINTRESOURCE(IDI_ICON2));
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.lpszMenuName=NULL;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH) GetStockObject(LTGRAY_BRUSH);
if(!RegisterClassEx(&wndclass)) return 0;
/*Initialize the common controls for WinXP look and feel*/
hmod=LoadLibrary("C:\\WINDOWS\\WinSxS\\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\\comctl32.dll");
if (!hmod)
{ MessageBox(NULL,"dll not loaded","error",MB_ICONERROR);
}
InitCommonControls=(void (*)(void)) GetProcAddress(hmod,
"InitCommonControls");
if(InitCommonControls==NULL){
MessageBox(NULL,"no entry point","error",MB_ICONERROR);
}
(*InitCommonControls)();
//FreeLibrary(hmod);
//hmod=NULL;
hInst=hThisInst;
hwnd=CreateWindow(
szWinName,
"Auto Timer (Work in progress)",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hThisInst,
NULL
);
while(GetMessage(&msg, NULL, 0, 0)>0)
{ if (!hDlg||!IsDialogMessage(hDlg,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wparam,
LPARAM lparam)
{
switch(message){
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hDlg=CreateDialog(hInst,MAKEINTRESOURCE(IDD_FORMVIEW),
hwnd,(DLGPROC)DialogFunc);
break;
default:
return DefWindowProc(hwnd,message,wparam,lparam);
}
return 0;
}
BOOL CALLBACK DialogFunc(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case WM_INITDIALOG:
SendMessage(hwnd,WM_SETICON, ICON_SMALL ,
(LPARAM)LoadIcon(hInst,MAKEINTRESOURCE(IDI_ICON2)));
break;
case WM_CTLCOLORSTATIC:
return (INT_PTR)GetStockObject(WHITE_BRUSH);
case WM_CLOSE:
DestroyWindow(hwnd);
hDlg=NULL;
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
If anyone wants the entire project please give me your mail id and I will send the entire project to them. I want to know exactly why this is happening not whether I should do it or not.Thank You.
The working case
Your manifest refences the Microsoft.Windows.Common-Controls assembly. This assembly is a collection of one or more DLLs and COM objects, it is not a .Net assembly. When your application is launched Windows creates an activation context. Any references to a DLL or COM object that is described in the assembly are redirected to the requested version. The activation context remains active during calls into comctl32.dll, so any calls it makes to DLLs or COM objects will also be redirected.
The not-working case
You load a specific version of comctl32.dll from \Windows\Sxs\. This references other DLLs or COM objects but, in the absence of an activation context, the wrong ones are loaded. And your application doesn't work.
Conclusion
I don't know if this is the specific problem in your case, but in general anything that lives in \Windows\Sxs is intended to run in a particular activation context, and you can't expect it to work outside of that context. Even if it did happen to work, it might break in the future. Don't do this.
Related
I use Visual Studio 2022 Community (17.1.3) with C++ 17
It was a pain to manage menus from the raw Win32 API, but with the help of the OOP, I have successfully encapsulated all functions related to menus, so I don't need to care anymore about indexes if I want to do something with one of the items inside a menu.
However, when the mouse cursor hits an item, VS throws the following exception:
wil::ResultException at memory location 0x[Address].
[Rethrow] at memory location 0x0000000000000000.
The app can still run (it doesn't crash, the exception is actually in the output window of VS!)
GetLastError() at the end of the execution returns 0. I can also retrieve what item has been clicked by the user with WM_COMMAND, and it works well.
I don't know whether it's normal or not, but I also tried to compile the template project and another project I've done in the past with the Win32 API, and guess what, the same happens. Hence I think it's not a specific problem related to my code (although I don't have much experience in C++, considering it's been only two years since I started to learn it), but a problem of the IDE itself.
main.cpp
// ---------- main.cpp
#include <Windows.h>
#include "resource.h"
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
// Globals
HINSTANCE inst;
HWND mainWnd;
HMENU menuBar;
HMENU subMenu1;
HMENU subMenu2;
int WINAPI wWinMain(HINSTANCE p_hInst, HINSTANCE p_hPrevInst, LPWSTR p_lpszArgs, int p_nCmdShow)
{
inst = p_hInst;
// register the main window class
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = WindowProc;
wcex.hInstance = inst;
wcex.lpszClassName = L"Menus";
if (!RegisterClassExW(&wcex))
{
// handle error
}
mainWnd = CreateWindowExW(NULL, L"Menus", L"Using menus",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, inst, NULL);
if (NULL == mainWnd)
{
// Handle error
}
ShowWindow(mainWnd, p_nCmdShow);
UpdateWindow(mainWnd);
// Create a message structure and start the main loop
MSG message;
while (GetMessage(&message, NULL, NULL, NULL))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return (int)message.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
// Create and set the menu
menuBar = CreateMenu();
subMenu1 = CreatePopupMenu();
subMenu2 = CreatePopupMenu();
AppendMenu(subMenu1, MF_STRING, ID_ITM1, L"Item 01");
AppendMenu(subMenu1, MF_STRING, ID_ITM2, L"Item 02");
AppendMenu(subMenu1, MF_SEPARATOR, NULL, NULL);
AppendMenu(subMenu1, MF_STRING, ID_ITMCLOSE, L"Close");
AppendMenu(subMenu2, MF_STRING, ID_ITMABOUT, L"About...");
AppendMenu(menuBar, MF_POPUP, (UINT_PTR)subMenu1, L"Menu");
AppendMenu(menuBar, MF_POPUP, (UINT_PTR)subMenu2, L"Help");
SetMenu(hWnd, menuBar);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_ITMABOUT:
MessageBox(mainWnd, L"Using menus -- Just an example for Stack Overflow", L"About...", MB_OK);
}
break;
case WM_DESTROY:
PostQuitMessage(GetLastError());
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
resource.h
#pragma once
#define ID_ITM1 5000
#define ID_ITM2 5100
#define ID_ITM3 5200
#define ID_ITM4 5300
#define ID_ITMCLOSE 5400
#define ID_ITMABOUT 5500
/* -------------------------------------------------------------
(Don't forget to add an empty line to avoid the "unexpected
end of line error of VS if you don't use the integrated resource
editor.")
------------------------------------------------------------- */
This sample contains the minimum code to create an empty window and assign it a menu.
If you highlight one of the items or click the "About" item and look at the Output window of VS, exceptions will start to throw without any reason, but the app will continue to run fine.
Please, note that it will take some seconds, be patient.
My Visual Studio Output Window looks like that.
Edit:
clearer explanations about the problem.
There's indeed a problem with menus in VS2022 (17.1.4, std/C++17 flag).
When I compile the code above (which does not contain any bugs), it throws the wil::ResultException in my output window, but the program itself continues to run fine.
I'm trying to make an application that gets informed on creation and destruction of top-level windows, system-wide. I've made a code to exploit a CBT hook. The solution contains two projects, DLL and EXE. EXE project has a reference to the DLL project. The hook is being set from a DLL. There is a message loop in EXE project. The problem is that CBT hook is not working. With the help of VS debugger, I've found out that hook callback is never called, while return code from SetWindowsHookEx is non-zero, implying the hook was set. What's a mistake? How do I fix it?
Here's a minimal example. DLL, main.cpp:
#include <windows.h>
typedef void(*DECODERPROC)(int code, WPARAM wParam, LPARAM lParam);
HINSTANCE hInst = nullptr;
HHOOK hHook = nullptr;
DECODERPROC fpDecoder = nullptr;
LRESULT CALLBACK cbtProc(int code, WPARAM wParam, LPARAM lParam) {
// FIXME: never called
if (code > 0 && fpDecoder) {
fpDecoder(code, wParam, lParam);
}
return CallNextHookEx(hHook, code, wParam, lParam);
}
__declspec(dllexport) bool InstallHook(DECODERPROC decoder) {
if (hHook) return false;
fpDecoder = decoder;
return (hHook = SetWindowsHookEx(WH_CBT, cbtProc, hInst, 0)) != NULL;
}
__declspec(dllexport) bool UninstallHook() {
if (!hHook) return false;
bool res = UnhookWindowsHookEx(hHook) != NULL;
if (res) hHook = NULL;
return res;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
hInst = reinterpret_cast<HINSTANCE>(hModule);
return TRUE;
}
EXE, main.cpp
#include <iostream>
#include <locale>
#include <windows.h>
#include <fcntl.h>
#include <io.h>
using namespace std;
typedef void(*DECODERPROC)(int code, WPARAM wParam, LPARAM lParam);
__declspec(dllimport) bool InstallHook(DECODERPROC);
__declspec(dllimport) bool UninstallHook();
int main() {
_setmode(_fileno(stdout), _O_U8TEXT);
WNDCLASS windowClass = {};
windowClass.lpfnWndProc = [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT {
if (message == WM_DESTROY)
UninstallHook();
return DefWindowProc(hWnd, message, wParam, lParam);
};
LPCWSTR windowClassName = L"Foobar";
windowClass.lpszClassName = windowClassName;
if (!RegisterClass(&windowClass)) {
wcerr << L"Failed to register window class" << endl;
return 1;
}
HWND messageWindow = CreateWindow(windowClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
if (!messageWindow) {
wcerr << L"Failed to create message-only window" << endl;
return 1;
}
InstallHook([](int code, WPARAM wParam, LPARAM lParam) {
wcout << L"Never called" << endl;
});
MSG msg;
while (GetMessage(&msg, 0, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
If you are running on Windows 64-bit, you need both 32-bit and 64-bit versions of the DLL in order to hook every running process. A 32-bit DLL cannot hook a 64-bit process, and vice versa. So you need to call SetWindowsHookEx() from a 32-bit process to hook 32-bit processes, and from a 64-bit process to hook 64-bit processes.
More importantly than that, a separate instance of your DLL gets injected into every running process, so your fpDecoder callback pointer is NULL in every instance of the DLL except for the one that your EXE is calling InstallHook() on. So you need to redesign your hook to use inter-process communication (window message, named pipe, mailslot, socket, etc) to communicate with your main EXE, you can't use a function pointer.
Depending on which process you are actually debugging, you might not see cbtProc() getting called. If you are debugging your main EXE process, your code is not doing anything to trigger any CBT activity within your EXE's process once the hook has been installed, and the debugger would not show you any CBT activity occurring in other processes that it is not debugging.
Depending on what you are actually looking for in your hook, you might consider using SetWinEventHook() instead, as it can be used with or without a DLL, and it has more flexible filtering capabilities than SetWindowsHookEx().
I'd like to build a win32 application using sdk 7.1, I create the dialog box using Visual C++ 2012 resource editor, I copy resource.rc and resource.h to my folder and I write this simple main.cpp file:
#include <windowsx.h>
#include <Windows.h>
#include <tchar.h>
#include "resource.h"
#define my_PROCESS_MESSAGE(hWnd, message, fn) \
case(message): \
return( \
SetDlgMsgResult(hWnd, uMsg, \
HANDLE_##message((hWnd), (wParam), (lParam), (fn)) )) \
LRESULT CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL Cls_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
int WINAPI _tWinMain( HINSTANCE hInstance,
HINSTANCE,
LPTSTR,
int iCmdLine )
{
DialogBoxParam( hInstance,
MAKEINTRESOURCE(IDD_INJECTOR),
NULL,
(DLGPROC) DlgProc,
NULL
);
return FALSE;
}
LRESULT CALLBACK DlgProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
switch (uMsg)
{
my_PROCESS_MESSAGE(hwnd, WM_INITDIALOG, Cls_OnInitDialog);
my_PROCESS_MESSAGE(hwnd, WM_COMMAND, Cls_OnCommand);
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
BOOL Cls_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
return TRUE;
}
void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch(id)
{
case IDCANCEL:
EndDialog(hwnd, id);
break;
default:
break;
}
}
then I use the following command line to compile my code, wich I found on this forum
cl main.cpp /link /SUBSYSTEM:WINDOWS user32.lib
my problem is that my dialog box did not show up, and when I use procexp, to see what happen, I found that that my application is created then closed in the same time, and what make me wondering is that its working fine on Visual C++ 2012.
my sdk 7.1, installed correctly, I testing it against a basic window without any resource file
You need to "compile" the resource file with the resource compiler:
rc -r resource.rc
That will give you resource.res. You need to link that in when you create your executable:
cl main.cpp resource.res /link /SUBSYSTEM:WINDOWS user32.lib
I haven't tested your code to see if it works then, but at least with the .res file linked in, it stands at lest some chance of working.
This isn't your only problem, but, from MSDN:
Although the dialog box procedure is similar to a window procedure, it must not call the DefWindowProc function to process unwanted messages. Unwanted messages are processed internally by the dialog box window procedure.
[Emphasis added.]
I've created a dialog box inside a Win32 DLL (using resource editor) and now want to show it as application program (using this DLL) calls DisplayDialog, but it is not working.
// AppProgram.cpp
...
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDM_FILE_NEW_DIALOG:
DisplayDialog (hInst, hWnd);
break;
...
}
break;
....
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
My DLL appears like
#include "stdafx.h"
#include "myDLL.h"
EXPORT BOOL CALLBACK DisplayDialog (HINSTANCE hInst, HWND hWnd) {
DialogBox (hInst, MAKEINTRESOURCE (IDD_DIALOG1), hWnd, reinterpret_cast<DLGPROC> (DiagProc));
// MessageBox works here
}
...
I've tested that this DLL displays dialog if the dialog belongs to AppProgram.
Here, I want to display dialog when it is a part of DLL.
Please suggest whether we should create dialog inside DLL or should pass it from program. + how to show dialog in given scenario. Thanks in advance.
The hInst parameter is the handle to the module that contains the dialog resource. If you want to get the dialog from the DL's resourcesL, then pass the handle to the DLL rather than the handle to the main application.
Something like this:
HMODULE module = LoadLibrary("MyDll.dll");
HRSRC res = FindResource(module, "#1234", RT_DIALOG);
DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)LoadResource(module, res);
DialogBoxIndirect(0, pTemplate, hwnd, dlgproc);
I am trying to create a simple window with C/C++ using the native Windows message queue system (without .NET). I followed the MSDN tutorial and wrote some basic code that creates an empty window:
void main()
{
HINSTANCE hinst;
HWND hwndMain;
WNDCLASSEX wnd;
MSG msg;
hinst = GetModuleHandle( NULL );
memset( &wnd, 0, sizeof( wnd ) );
wnd.cbSize = sizeof( wnd );
wnd.lpszClassName = "MainWClass";
wnd.lpfnWndProc = MainWProc;
wnd.hInstance = hinst;
int result = RegisterClassEx( &wnd );
if( !result )
{
printf("RegisterClassEx error: %d\r\n", GetLastError() );
}
hwndMain = CreateWindowEx
(
0, //extended styles
wnd.lpszClassName, //class name
"Main Window", //window name
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
CW_USEDEFAULT, //horizontal position
CW_USEDEFAULT, //vertical position
CW_USEDEFAULT, //width
CW_USEDEFAULT, //height
(HWND) NULL, //parent window
(HMENU) NULL, //class menu
(HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
NULL //Create Window Data?
);
if( !hwndMain )
{
printf("Oh shi- %d\n", GetLastError() );
}
ShowWindow( hwndMain, SW_SHOWDEFAULT );
UpdateWindow( hwndMain );
}
When I run/debug the program, CreateWindowEx returns 0 which means it failed. This triggers the error message "Oh shi- [error code]". The most confusing part is that the error message prints to console:
Oh shi- 0
The error code returned by GetLastError() is 0, which is ERROR_SUCCESS!
I am at a total loss; what is happening? I am so confuse...
P.S.
I am using Visual C++ Express 2010 on Windows 7 32-bit. I have written a Windows Procedure elsewhere but it simply returns 0 for all cases. If, however, anyone wants to see it, I will be happy to show it.
I have changed the Project Default character set of my Visual C++ project to "Not Set". I should not need to prefix L to my things.
Edit: added wnd.hInstance = hinst;
Edit: removed the unnecessary (WNDPROC) cast
Edit: added error checking for RegisterClassEx
It turns out that the problem was with Visual C++ Express (or at least not with the code itself). I copied the code to another project and it worked.
wnd.lpfnWndProc = (WNDPROC) MainWProc;
We can't see the real reason you need to use the cast but it is very fishy. Windows returns 0 from GetLastError() if it didn't see anything going wrong. Which can happen if the window procedure is broken. Like this one:
LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}
Windows sends the WM_NCCREATE message to ask for the window to be created. If that message doesn't get processed then there will be no window. And no error. Fix:
LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Tweak as necessary to customize the window. Just make sure that DefWindowProc() gets called for every message that you don't want to handle yourself. And keep Petzold close at hand to avoid the simple mistakes. And lose the cast.
All modern versions of Windows use Unicode internally, and by default, Visual Studio projects #define _UNICODE/UNICODE, which causes your application to link to the Unicode versions of the Windows headers.
When you're compiling an application as Unicode, however, the character (and thus "string") types are different. Instead of char, they're now wchar_t. That means that you have to explicitly declare your string literals as long strings by prefixing them with an L.
Alternatively, the Windows headers hide all of this behind macros, but it's no longer necessary because Windows has been Unicode for a long time and that's very unlikely to change.
Beyond that, you're missing several things in your initialization of the WNDCLASSEX structure, like the hInstance member. These things all have to be set perfectly, or things will fail. As well, the RegisterClass(Ex) and CreateWindow(Ex) functions must be passed the exact same string values corresponding to the name of the window class, otherwise they will assume you're talking about two different things. Typos are not forgiven!
I highly recommend that you use the Visual Studio wizards to create a blank (but working!) project template.
The correct boilerplate code goes something like this:
#include <windows.h>
#include <tchar.h>
// Define these here to minimize typos, or preferably, load them from a
// resource file at the top of the main function
#define MYCLASSNAME TEXT("MainWndClass")
#define MYWINDOWNAME TEXT("Main Window")
// Global variable to keep track of your hInstance
HINSTANCE g_hInstance;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// If you don't process any of the messages yourself, you
// must pass them to DefWindowProc for default handling.
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
// Save the instance handle in a global variable.
g_hInstance = hInstance;
// Register your window class.
// (A full-featured app will probably want to set additional members.)
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(wcex);
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.lpszClassName = MYCLASSNAME;
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL, TEXT("Call to RegisterClassEx failed!"), NULL, MB_OK);
return 1;
}
// Create your main window.
HWND hwndMain = CreateWindowEx(0, MYCLASSNAME, MYWINDOWNAME, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
hInstance, NULL);
if (!hwndMain)
{
MessageBox(NULL, TEXT("Call to CreateWindowEx failed!"), NULL, MB_OK);
return 1;
}
// Show your main window.
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
// Run the main message loop.
BOOL bRetVal;
MSG msg;
while ((bRetVal = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRetVal == -1)
{
MessageBox(NULL, TEXT("Error encountered in message loop!"), NULL, MB_OK);
return 1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
I had the same problem.
In my case its just that i used visual sutdio without admin rights.
And i discovered that in this case i cant debug my application.
In debug mode without admin right, CreateWindowEx return null with error code result to 0 like you.
But if you go to your build directory you can use your app (not in debug mode).
So if this the case fro you too, just start visula studio with admin right and its done.
I think there is almost a way to use visual studio debug mode with admin right without start visual stuido with admin password each time. i dont know how to do that, but i think it may be possible.
In my case i had to handle WNC_NCCREATE manually. DefWindowProc returned zero for WNC_NCCREATE, i fixed that with:
LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WNC_NCCREATE)
return true;
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}