Win32 save text files from tabbed interface - winapi

I'm using MS visual c++ 2010 express to write a notepad program. I need to be able to save files from my tabbed interface ( each edit control is stored into a vector ). I can't seem to figure out how to save, depending on which edit control is visible to the user ( active tab ). Everything I've tried so far either doesn't save the contents or only saves from the first edit control. When the user adds a new file to the tabbed interface, it added that edit control to the back of the vector. This is my latest attempt:
std::vector<HWND>vect;
BOOL SaveTextFileFromEdit( HWND hEdit, LPCTSTR pszFileName )
{
HANDLE hFile;
BOOL bSuccess = FALSE;
hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
DWORD dwTextLength = GetWindowTextLength( hEdit );
if( dwTextLegth > 0 )
{
DWORD dwBufferSize = dwTextLength + 1;
LPSTR pszText = ( LPSTR )GlobalAlloc( GPTR, dwBufferSize );
if( pszText != NULL )
{
if( GetWindowText( hEdit, pszText, dwBufferSize ) )
{
DWORD dwWritten;
if( WriteFile( hFile, pszText, dwTextLength, &dwWritten, NULL ) )
bSuccess = TRUE;
}
GlobalFree( pszText );
}
}
CloseHandle( hFile );
}
return bSuccess;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case ID_FILE_SAVEAS:
{
OPENFILENAME ofn;
char szFileName[ MAX_PATH ] = "";
ZeroMemory( &ofn, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = "txt";
ofn.flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if( GetSaveFileName( &ofn ) )
{
HWND hEdit, hTabs;
hTabs = GetDlgItem( hwnd, IDC_MAIN_TAB );
int curTab = TabCtrl_GetCurSel( hTabs );
hEdit = GetDlgItem( hTabs, IDC_MAIN_EDIT );
// This is what i did have: hEdit = GetDlgItem( vect[ curTab ], IDC_MAIN_EDIT );
// Which wasn't saving anything
if( SaveTextFileFromEdit( hEdit, szFileName ) )
{
// EVERYTHING IS GOOD
}
}
}
break;
}
break;
}
return 0;
}

If the vector has each edit control's HWND then you don't need GetDlgItem at all: You already have the HWND that it would return.
hEdit = vect[ curTab ];

Related

WM_PAINT message, BeginPaint loop

I can't understand why I got a loop on BeginPaint function. I have already read posts about this kind of loop but almost all of them recommend: "Don't forget to use BeginPaint function on WM_PAINT message, because it entails subsequent WM_PAINT messages otherwise". This isn't my case. May you give me some advices?
This is my windowclass ("CWindow"):
class CWindow {
public:
CWindow();
virtual ~CWindow();
bool RegisterClass(HINSTANCE hInstance);
bool CreateWnd(HINSTANCE hInstance);
bool Show(int nShow);
private:
HWND handleWindow;
ATOM atom;
bool isRegistered;
bool isCreated;
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void OnPaint();
void OnDestroy();
};
WndProc function.
LRESULT CALLBACK CWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CWindow* windowPtr = reinterpret_cast<CWindow*> ( GetWindowLongPtr( hWnd, GWLP_USERDATA ) );
PAINTSTRUCT ps;
HDC hdc;
switch( msg ) {
case WM_PAINT:
// There is a loop right here!
hdc = BeginPaint( windowPtr->handleWindow, &ps );
// The code below doesn't executed!
RECT rect;
(void)GetClientRect(windowPtr->handleWindow, &rect);
(void)DrawText(hdc, TEXT("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint( windowPtr->handleWindow, &ps );
break;
case WM_DESTROY:
windowPtr->OnDestroy();
break;
default:
return DefWindowProc( hWnd, msg, wParam, lParam );
}
return 0;
}
RegisterClass
bool CWindow::RegisterClass(HINSTANCE hInstance)
{
const TCHAR app_name[] = TEXT("HelloWin");
WNDCLASSEX windowClass;
ZeroMemory( &windowClass, sizeof(windowClass) );
windowClass.cbSize = sizeof(windowClass);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WindowProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = 0;
windowClass.hIcon = 0;
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = 0;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = app_name;
windowClass.hIconSm = NULL;
atom = RegisterClassEx( &windowClass );
DWORD errorCode = GetLastError();
if( errorCode ) {
isRegistered = 0;
std::wcout << L"ErrorCode: " << errorCode << std::endl;
} else {
isRegistered = 1;
}
return isRegistered;
}
CreateWindow
bool CWindow::CreateWnd(HINSTANCE hInstance)
{
handleWindow = CreateWindow((PCTSTR)atom, // window class name or atom
TEXT("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
DWORD errorCode = GetLastError();
if( !handleWindow ) {
isCreated = 0;
} else {
isCreated = 1;
}
return isCreated;
}
Show
bool CWindow::Show(int nShow)
{
if( isCreated ) {
ShowWindow( handleWindow, nShow );
return UpdateWindow( handleWindow );
} else {
return 0;
}
}
WinMain
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevINstance, LPSTR lpCmdLine, int nShow )
{
CWindow window;
window.RegisterClass( hInstance );
window.CreateWnd( hInstance );
window.Show( nShow );
int response = 0;
MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return 0;
}
Since you never call SetWindowLongPtr,
CWindow* windowPtr = reinterpret_cast<CWindow*>( GetWindowLongPtr( hWnd, GWLP_USERDATA ) );
returns a nullptr, that you subsequently try to dereference:
BeginPaint( windowPtr->handleWindow, &ps )
That will trigger an access violation exception, causing the BeginPaint call to never even get executed, leaving the invalid region as is. As a consequence, the system keeps generating WM_PAINT messages. That's the same issue as not calling BeginPaint altogether.1
To solve this, you'll either have to attach the window handle to the window instance by calling SetWindowLongPtr, or simply use the hWnd parameter that's passed into your CWindow::WindowProc.
1 Note that the system silently handles unhandled exceptions in your WindowProc on 64-bit versions of Windows under certain conditions.

Ruby implementation Win32API get mouse scroll/wheel input

I'm trying to use win32api on user32.dll to get mouse wheel input.
I tried the following:
#state = Win32API.new('user32','DefWindowProc',['i'],'i')
p #state.call(0x0800)
But it keeps returning 0 no matter what I do with my mouse wheel.
I thought something is wrong with my mouse, so I tried to do:
#state = Win32API.new('user32','GetKeyState',['L'],'L')
p #state.call(0x01) #left key
p #state.call(0x02) #right key
It worked, so I'm not sure what's wrong with the mouse wheel.
Regards
Edit 2/20/2014:
I tried to do the following:
GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')
DefWindowProc.call(GetActiveWindow.call,
Then, I got stuck with the UINT / Message (2nd argument).
Edit 2/20/2014:
I found the WM_MOUSEWHEEL message
Latest revision:
GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')
#WM_MOUSEWHEEL message 0x020A
DefWindowProc.call(GetActiveWindow.call, 0x020A,
Now I just need to figure out the 3rd and 4th argument.
As I don't know Ruby, I will give here a solution in C/C++ using only standard Win32 APIs. If you can call Win32 APIs from Ruby, that will work.
Note that the solution involves "callback" and "pointer". I know that's possible in Python (for example, with the ctypes module) and hope that same thing is possible with Ruby.
Register a Window Class and create a Window from that class, the window will be a Message-Only Window, so it will be invisible, with no GUI.
Use the RegisterRawInputDevices API to ask for raw events from mouse devices.
Set up a message loop, with the standard GetMessage/DispatchMessage combo.
Process the sent WM_INPUT message in your Window Procedure
4.1. Allocate memory for the raw datas
4.2. Retrieve the raw datas
4.3. Filter for mouse event and wheel datas
4.4. Process (I just print the wheel delta)
4.5. Free allocated memory.
Below, full source code. Build with VS2012 Express on Windows 7.
#include <Windows.h>
#include <stdio.h>
LRESULT CALLBACK MyWindowProc( HWND, UINT, WPARAM, LPARAM );
int main( void ) {
WNDCLASS WndClass;
memset( &WndClass, 0, sizeof( WndClass ) );
WndClass.hInstance = GetModuleHandle( NULL );
WndClass.lpszClassName = L"MyRawInputClass";
WndClass.lpfnWndProc = MyWindowProc;
RegisterClass( &WndClass );
HWND hWnd = CreateWindow( WndClass.lpszClassName, NULL, 0, 0, 0, 0, 0,
HWND_MESSAGE, 0, WndClass.hInstance, 0 );
RAWINPUTDEVICE RawInputDevice;
RawInputDevice.usUsagePage = 0x01; // Generic Desktop Controls
RawInputDevice.usUsage = 0x02; // Mouse
RawInputDevice.dwFlags = RIDEV_INPUTSINK;
RawInputDevice.hwndTarget = hWnd;
BOOL bWin32Success = RegisterRawInputDevices( &RawInputDevice, 1,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
BOOL bRet;
MSG msg;
while( ( bRet = GetMessage( &msg, hWnd, 0, 0 ) ) != 0 ) {
if (bRet != -1) {
DispatchMessage(&msg);
}
}
// NO GUI, UNREACHABLE
DestroyWindow( hWnd );
UnregisterClass( WndClass.lpszClassName, WndClass.hInstance );
return 0;
}
LRESULT CALLBACK MyWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) {
switch ( uiMsg ) {
case WM_INPUT: {
UINT dwSize;
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>( lParam );
UINT uiRetCode = GetRawInputData( hRawInput, RID_INPUT, NULL, &dwSize,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
if ( uiRetCode != 0xffffffff ) {
LPBYTE lpb = new BYTE[ dwSize ];
uiRetCode = GetRawInputData( hRawInput, RID_INPUT, lpb, &dwSize,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
if ( uiRetCode > 0 ) {
RAWINPUT* praw = reinterpret_cast<RAWINPUT*>( lpb );
if ( praw->header.dwType == RIM_TYPEMOUSE ) {
if ( praw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL ) {
signed int siDelta = static_cast<SHORT>( praw->data.mouse.usButtonData );
printf( "WHEEL EVENT: Delta = %d\n", siDelta );
}
}
}
delete[] lpb;
}
break;
} // WM_INPUT
default:
return DefWindowProc( hWnd, uiMsg, wParam, lParam );
}
return 0;
}

Why is MiniDumpWriteDump failing?

I have created my own debugger application. It attaches to a process and creates a crash dump file. That works most of the time. The problem I have is that it will not work when the application being debugged is waiting for a mutex object (and this is the very problem that I want to debug).
Furthermore, I have created a simple test.exe application that just loops around and calls Sleep(100) but my debugger fails when it calls MiniDumpWriteDump on this application every time.
What am I doing wrong?
The error code I get returned from the code below is 2147942699 (0x8007012b)
void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
CONTEXT c;
memset( &c, 0, sizeof( c ) );
GetThreadContext( hThread, &c );
EXCEPTION_POINTERS ep;
memset( &ep, 0, sizeof( ep ) );
ep.ContextRecord = &c;
ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;
MINIDUMP_EXCEPTION_INFORMATION minidump_exception;
memset( &minidump_exception, 0, sizeof( minidump_exception ) );
minidump_exception .ThreadId = dwThreadId;
minidump_exception.ExceptionPointers = &ep;
minidump_exception.ClientPointers = true;
char txDumpPath[ MAX_PATH + 1 ];
sprintf( txDumpPath, "%s.dmp", txProcess );
HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile )
{
BOOL fSuccess;
SetLastError( 0L );
int nDumpOptions =
MiniDumpNormal
| MiniDumpWithDataSegs
| MiniDumpWithFullMemory
| MiniDumpWithHandleData
| MiniDumpFilterMemory
| MiniDumpScanMemory
| MiniDumpWithUnloadedModules
| MiniDumpWithIndirectlyReferencedMemory
| MiniDumpFilterModulePaths
| MiniDumpWithProcessThreadData
| MiniDumpWithPrivateReadWriteMemory
| MiniDumpWithoutOptionalData
;
fSuccess = MiniDumpWriteDump( hProcess,
dwProcessId,
hFile,
(MINIDUMP_TYPE) nDumpOptions,
&minidump_exception,
NULL,
NULL );
DWORD dwErr = GetLastError();
if( ! fSuccess )
printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );
CloseHandle( hFile );
}
}
I have also tried increasing the privileges with the following code snippet which I borrowed from somebody else who seemed to have a similar problem:
BOOL SetDumpPrivileges()
{
BOOL fSuccess = FALSE;
HANDLE TokenHandle = NULL;
TOKEN_PRIVILEGES TokenPrivileges;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&TokenHandle))
{
printf("Could not get the process token");
goto Cleanup;
}
TokenPrivileges.PrivilegeCount = 1;
if (!LookupPrivilegeValue(NULL,
SE_DEBUG_NAME,
&TokenPrivileges.Privileges[0].Luid))
{
printf("Couldn't lookup SeDebugPrivilege name");
goto Cleanup;
}
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//Add privileges here.
if (!AdjustTokenPrivileges(TokenHandle,
FALSE,
&TokenPrivileges,
sizeof(TokenPrivileges),
NULL,
NULL))
{
printf("Could not revoke the debug privilege");
goto Cleanup;
}
fSuccess = TRUE;
Cleanup:
if (TokenHandle)
{
CloseHandle(TokenHandle);
}
return fSuccess;
}
I posted a question on MSDN and somebody kindly provided me the answer to my problem. Here's the link to the discussion, and the working code snippet I've copied below.
void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
CONTEXT c;
memset( &c, 0, sizeof( c ) );
HANDLE hThread;
c.ContextFlags = CONTEXT_FULL;
hThread = _OpenThread( THREAD_ALL_ACCESS, FALSE, dwThreadId );
GetThreadContext( hThread, &c );
EXCEPTION_POINTERS ep;
memset( &ep, 0, sizeof( ep ) );
ep.ContextRecord = &c;
ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;
MINIDUMP_EXCEPTION_INFORMATION minidump_exception;
memset( &minidump_exception, 0, sizeof( minidump_exception ) );
minidump_exception.ThreadId = dwThreadId;
minidump_exception.ExceptionPointers = &ep;
minidump_exception.ExceptionPointers->ContextRecord = &c;
minidump_exception.ClientPointers = false;
char txDumpPath[ MAX_PATH + 1 ];
time_t tNow = time( NULL );
struct tm *pTm = localtime( &tNow );
sprintf( txDumpPath, "%s.%02d%02d%04d_%02d%02d%02d.dmp",
txProcess,
pTm->tm_mday,
pTm->tm_mon,
pTm->tm_year,
pTm->tm_hour,
pTm->tm_min,
pTm->tm_sec );
HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
BOOL fSuccess;
printf( "hProcess : %d (0x%x)\n", hProcess, hProcess );
printf( "dwProcessId: %u (0x%lx)\n", dwProcessId, dwProcessId );
printf( "dwThreadId : %u (0x%lx)\n", dwThreadId, dwThreadId );
SetLastError( 0L );
fSuccess = MiniDumpWriteDump( hProcess,
dwProcessId,
hFile,
MiniDumpNormal,
&minidump_exception,
NULL,
NULL );
DWORD dwErr = GetLastError();
if( ! fSuccess )
{
printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
// Display the string.
printf( "%s\n", (LPCTSTR)lpMsgBuf );
// Free the buffer.
LocalFree( lpMsgBuf );
}
}
if( hThread )
CloseHandle( hThread );
}
Is this problem the same one as the other question I answered with this text?
Does it not include the mutex information even with flag MiniDumpWithHandleData, also it is possibly failing because some of the flags may not be compatible with the version of DebugHlp.dll you are calling against see: here

WM_COMMAND message not being received by the Windows Procedure

I am creating a system tray program with a shortcut/context menu, but I can't seem to receive WM_COMMAND messages in the Windows Procedure. It simply doesn't send when I click the menu item, and I've been checking for ages whether I have set up the menu correctly.
Here is my code:
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#define WM_TRAYICON (WM_USER + 0x0001) //a custom message for the notification icon
HWND hwnd; //window handle
HINSTANCE hinst; //module handle
WNDCLASSEX wnd; //window class
MSG msg; //event message or notification
NOTIFYICONDATA nid; //notification icon object
HMENU cmenu;
MENUITEMINFO menuitem1;
MENUITEMINFO menuitem2;
CURSORINFO cursor;
LRESULT CALLBACK MainWProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_COMMAND:
printf("asfd\r\n");
break;
case WM_CREATE:
printf("just created\r\n");
break;
case WM_TRAYICON:
switch( LOWORD(lParam) )
{
case WM_CONTEXTMENU:
GetCursorInfo( &cursor );
//printf("xPos: %d\r\nyPos = %d\r\n\r\n", xPos, yPos );
TrackPopupMenuEx( cmenu, TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_NOANIMATION | TPM_HORIZONTAL | TPM_VERTICAL, cursor.ptScreenPos.x, cursor.ptScreenPos.y, hwnd, NULL );
//DestroyMenu(
break;
}
break;
case WM_INITMENU:
printf("open menu\r\n");
break;
case WM_DESTROY:
//clean things up
Shell_NotifyIcon( NIM_DELETE, &nid );
break;
default:
break;
}
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
void main()
{
int result;
hinst = GetModuleHandle( NULL );
cursor.cbSize = sizeof( cursor );
memset( &wnd, 0, sizeof( wnd ) );
wnd.cbSize = sizeof( wnd );
wnd.lpszClassName = "MainWClass";
wnd.lpfnWndProc = MainWProc;
wnd.hInstance = hinst;
result = RegisterClassEx( &wnd );
hwnd = 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( !hwnd )
{
printf("CreateWindowEx failed: %d\n", GetLastError() );
Sleep( INFINITE );
}
nid.cbSize = sizeof( nid );
nid.hWnd = hwnd;
nid.uID = 1;
nid.uVersion = NOTIFYICON_VERSION_4;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon( hinst, MAKEINTRESOURCE( IDI_ICON1 ) );
strcpy( nid.szTip, "My Tooltip!" );
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_SHOWTIP;
cmenu = CreatePopupMenu();
menuitem1.cbSize = sizeof( menuitem1 );
menuitem1.fMask = MIIM_TYPE;
menuitem1.fType = MFT_STRING;
menuitem1.hSubMenu = NULL;
//menuitem1.cch = ;
menuitem1.dwTypeData = "Open a world of wonder!";
InsertMenuItem( cmenu, 0, true, &menuitem1 );
if( ! Shell_NotifyIcon( NIM_ADD, &nid ) )
{
printf("Shell_NotifyIcon( NIM_ADD, &nid ) failed.\r\n");
Sleep( INFINITE );
}
if( ! Shell_NotifyIcon( NIM_SETVERSION, &nid ) )
{
printf("Shell_NotifyIcon( NIM_SETVERSION, &nid ) failed.\r\n");
Sleep( INFINITE );
}
UpdateWindow( hwnd );
for( ; ; )
{
if( GetMessage(&msg, hwnd, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Um, you passed the TPM_RETURNCMD flag which means "don't post a WM_COMMAND message. Just return the value you would have posted."

Win32: No Window Appears

I was programming the example code from Frank Luna's book "Introduction to 3D Game Programming with DirectX 10". The code is the first Win32 example in the Appendix A: Windows Programming section.
Right now, the program compiles under both VC++ 2008/2010, but no window appears, although the debug session has started and I have to forcefully close it. I have no idea where it is, I'm not using Win32 Console mode, I have closed all other windows and no other IDE or session of VC++ is running.
Any idea why this might be happening?
PS: I have also checked my Processes. It is indeed running.
#include <Windows.h>
HWND ghMainWnd = 0;
bool InitWindowsApp(HINSTANCE instanceHandle, int show);
int Run();
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI
WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd )
{
if( !InitWindowsApp(hInstance, nShowCmd) )
return 0;
return Run();
}
bool InitWindowsApp( HINSTANCE instanceHandle, int show )
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"BasicWndClass";
if( !RegisterClass(&wc) )
{
MessageBox(0, L"RegisterClass FAILED", 0, 0);
return false;
}
ghMainWnd = CreateWindow(
L"BasicWndClass",
L"Win32Basic",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
if( ghMainWnd = 0 )
{
MessageBox( 0, L"Window Creation FAILED", 0, 0 );
return false;
}
ShowWindow( ghMainWnd, show );
UpdateWindow( ghMainWnd );
return true;
}
int Run()
{
MSG msg = {0};
BOOL bRet = 1;
while( bRet = GetMessage( &msg, 0, 0, 0 ) != 0 )
{
if( bRet == -1 )
{
MessageBox( 0, L"GetMessage FAILED", 0, 0 );
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK
WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_LBUTTONDOWN:
MessageBox( 0, L"Hello, World", 0, 0 );
return 0;
case WM_KEYDOWN:
if( wParam == VK_ESCAPE )
DestroyWindow( ghMainWnd );
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Change this:
if( ghMainWnd = 0 )
{
MessageBox( 0, L"Window Creation FAILED", 0, 0 );
return false;
}
to:
if( ghMainWnd == 0 )
{
MessageBox( 0, L"Window Creation FAILED", 0, 0 );
return false;
}
Two equals signs instead of one. :)
Wild guess: _UNICODE is not defined by project settings. Use CreateWindowW, RegisterClassW, to avoid dependency.

Resources