IDD_ABOUT: undeclared identifier - c++

I'm new to c / c++ programing language and am following an online tutorial about Win32. When I build and compile my project ( MS VS C++ 2010 Express ), i get this error: 'IDD_ABOUT' : undeclared identifier. I'm not sure how to fix this. :(
Main.cpp:
#include <Windows.h>
#define ID_FILE_EXIT 9001
#define ID_HELP_ABOUT 9002
const char g_szClassName[] = "myWindowClass";
BOOL CALLBACK AboutDlgProc( HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam )
{
switch( Message )
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case IDOK:
EndDialog( hwnd, IDOK );
break;
case IDCANCEL:
EndDialog( hwnd, IDCANCEL );
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_CREATE:
{
HMENU hMenu, hSubMenu;
HICON hIcon, hIconSm;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu( hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit" );
AppendMenu( hMenu, MF_STRING | MF_POPUP, ( UINT )hSubMenu, "&File" );
hSubMenu = CreatePopupMenu();
AppendMenu( hSubMenu, MF_STRING, ID_HELP_ABOUT, "&About" );
AppendMenu( hMenu, MF_STRING | MF_POPUP, ( UINT )hSubMenu, "&Help" );
SetMenu( hwnd, hMenu );
hIcon = ( HICON )LoadImage( NULL, "menu_one.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE );
if( hIcon )
SendMessage( hwnd, WM_SETICON, ICON_BIG, ( LPARAM )hIcon );
else
MessageBox( hwnd, "Could not load large icon!", "ERROR!", MB_OK | MB_ICONERROR );
hIconSm = ( HICON )LoadImage( NULL, "menu_one.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE );
if( hIconSm )
SendMessage( hwnd, WM_SETICON, ICON_SMALL, ( LPARAM )hIconSm );
else
MessageBox( hwnd, "Could not load small icon!", "ERROR!", MB_OK | MB_ICONERROR );
}
break;
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case ID_FILE_EXIT:
PostMessage( hwnd, WM_CLOSE, 0, 0 );
break;
case ID_HELP_ABOUT:
{
int ret = DialogBox( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDD_ABOUT ), hwnd, AboutDlgProc );
if( ret == IDOK )
MessageBox( hwnd, "Dialog exited with IDOK.", "Notice", MB_OK | MB_ICONINFORMATION );
else if( ret == IDCANCEL )
MessageBox( hwnd, "Dialog exited with IDCANCEL.", "Notice", MB_OK | MB_ICONINFORMATION );
else if( ret == -1 )
MessageBox( hwnd, "Dialog failed!", "Error", MB_OK | MB_ICONINFORMATION );
}
break;
}
break;
case WM_LBUTTONDOWN:
break;
case WM_CLOSE:
DestroyWindow( hwnd );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
// Step 1: Registering the Window Class
wc.cbSize = sizeof( WNDCLASSEX );
wc.style = 1;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = NULL;
if( !RegisterClassEx( &wc ) )
{
MessageBox( NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK );
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
500, 200, 800, 600,
NULL, NULL, hInstance, NULL );
if( hwnd == NULL )
{
MessageBox( NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK );
return 0;
}
ShowWindow( hwnd, nCmdShow );
UpdateWindow( hwnd );
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return msg.wParam;
}
Resource.rc:
#include <Windows.h>
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "My About Box"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
PUSHBUTTON "&Cancel",IDCANCEL,174,35,50,14
GROUPBOX "About this program...",IDC_STATIC,7,7,225,52
CTEXT "An example program showing how to use Dialog Boxes\r\n\r\nby theForger",IDC_STATIC,16,18,144,33
END

I have a feeling that Visual Studio Express doesn't include a proper resource editor that auto-generates resource includes, so I'm guessing you've created the .rc file manually. If so, you probably just need to define the symbol. Create an include file called resource.h and add this line to it:
#define IDD_ABOUT 100
Then include it at the top of your .cpp and .rc files:
#include <Windows.h>
#include "resource.h" // add this line
The windows headers define generic certain resource IDs (IDOK, IDCANCEL, IDC_STATIC, etc) but for anything else you'll need to add your own symbol. The values don't really matter - any number up to 65534 is ok as long as it doesn't clash with any other ID in use in the same "scope" (e.g. two controls in the one dialog should have different IDs, but you can re-use the same ID in another dialog).

Related

Cant create window using CreateWindowEx function

I cant create the window using code below although i get no error in compilation.Only a window with title of my project name appears.I also set hwnd=NULL after CreateWindowEx invocation to see whether MessageBox works but it does not work too.
#include <windows.h>
#include <StdAfx.h>
const char* myClassName="myWindowsClassName";
//The window procedure
LRESULT CALLBACK WndProc( HWND hwnd , UINT msg , WPARAM wParam , LPARAM lParam){
switch(msg){
case WM_CLOSE:
DestroyWindow( hwnd );
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc( hwnd , msg , wParam , lParam );
}
return 0;
}
//Registering window
int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lPCmdLine , int nCmdShow ){
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
wc.cbSize=sizeof( WNDCLASSEX );
wc.style=0;
wc.lpfnWndProc= WndProc;
wc.cbClsExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon( NULL , IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL , IDC_ARROW);
wc.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
wc.lpszClassName= (LPCWSTR) myClassName;
wc.hIconSm=LoadIcon( NULL , IDI_APPLICATION );
if( !RegisterClassEx( &wc ) ){
MessageBox( NULL ,L"Window registeration failed" ,L"Error!" , MB_ICONEXCLAMATION | MB_OK );
return 0;
}
//Creating the window
hwnd=CreateWindowEx( WS_EX_CLIENTEDGE , (LPCWSTR)myClassName , L"The title of my window" , WS_OVERLAPPEDWINDOW , CW_USEDEFAULT , CW_USEDEFAULT, 320 , 240 , NULL , NULL , hInstance , NULL );
hwnd=NULL;
if( hwnd==NULL ){
MessageBox( NULL ,L"Window creation failed",L"Error!", MB_ICONEXCLAMATION | MB_OK );
return 0;
}
ShowWindow ( hwnd , nCmdShow );
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Where is the problem?
Thanks
Unicode vs ANSI mismatch?
myClassName is char* but you cast it to (LPCWSTR). If you are compiling as Unicode (and you should) then you should define the class name as const WCHAR* myClassName=L"myWindowsClassName"; and remove the casts (or use const_cast<LPTSTR>().
You also fail to initialize .cbWndExtra. Change WNDCLASSEX wc; to WNDCLASSEX wc = {};
You should perform better error checking to diagnose failures. Check on MSDN to see if a function sets the last error when it fails. If it does, call GetLastError() after the function fails.

c++ win32 listbox and slider create windows application

I want to implement a listbox and a slider in my window.
I use devcpp, not visual studio.
I have looked up for a way to do that and i have found nothing, except theoritical stuff like msdn.microsoft.com provides.
I want an example, the smallest kind of code to implement listbox and slider.
This is the closer and most helpfull link, but still, it uses visual studio.
Thanks.
I found what i was looking for, it seems that this is the only example code on the entire internet on making listboxes. In order to run it: download and open devc++ (which I use) or any other kind of compiler, open a new Windows application project (otherwise it won't work), erase any default code, paste this code and run it.
And this, is how you help others learn code.
http://www.dreamincode.net/forums/topic/291276-win32-listbox/
#include <Windows.h>
#define IDC_MAIN_BUTTON 101 // Button identifier
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND hWndListL;
HWND hWndListR;
HWND hWndButton;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG Msg;
HWND hWnd;
//Settings All Window Class Variables
WNDCLASSEX WndClsEx;
WndClsEx.cbSize = sizeof(WNDCLASSEX);
WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
WndClsEx.lpfnWndProc = WndProcedure;
WndClsEx.cbClsExtra = 0;
WndClsEx.cbWndExtra = 0;
WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClsEx.hInstance = hInstance;
WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClsEx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
WndClsEx.lpszMenuName = NULL;
WndClsEx.lpszClassName = "My Window";
//Register Window Class
RegisterClassEx(&WndClsEx);
//Create Window
hWnd = CreateWindowEx(NULL, "My Window", "Windows Application", WS_OVERLAPPEDWINDOW, 200, 200, 640, 480, NULL, NULL, hInstance, NULL);
SendMessage(hWndListL, LB_ADDSTRING, NULL, (LPARAM)"one");
SendMessage(hWndListL, LB_ADDSTRING, NULL, (LPARAM)"two");
//Show Window
ShowWindow(hWnd, SW_SHOWNORMAL);
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
char buffer[50] = "";
switch(Msg)
{
case WM_CREATE:
//Create Listbox's
hWndListL = CreateWindowEx(NULL, "LISTBOX", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | LBS_NOTIFY, 50, 35, 200, 100, hWnd, NULL, GetModuleHandle(NULL), NULL);
hWndListR = CreateWindowEx(NULL, "LISTBOX", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | LBS_NOTIFY, 350, 35, 200, 100, hWnd, NULL, GetModuleHandle(NULL), NULL);
//Create Button
hWndButton = CreateWindowEx(NULL, "BUTTON", "OK", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_DISABLED, 50, 220, 100, 24, hWnd, (HMENU)IDC_MAIN_BUTTON, GetModuleHandle(NULL), NULL);
break;
case WM_COMMAND:
switch(HIWORD(wParam))
{
case LBN_SELCHANGE:
{
//EnableWindow( GetDlgItem( hWnd, (HMENU)IDC_BUTTON_MAIN ), TRUE );
EnableWindow(hWndButton, true);
break;
}
}
switch(LOWORD(wParam))
{
case IDC_MAIN_BUTTON:
{
//length = SendMessage(hWndListL, LB_GETTEXTLEN, NULL, NULL);
SendMessage(hWndListL, LB_GETTEXT, NULL, (LPARAM)buffer);
SendMessage(hWndListR, LB_ADDSTRING, NULL, (LPARAM)buffer);
SendMessage(hWndListL, LB_DELETESTRING, NULL, NULL);
EnableWindow(hWndButton, false);
break;
}
}
break;
case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
Here is example code of window with listbox:
#include <Windows.h>
/// unique class name
#define CLASS_NAME "MyWinapiClassNameWithUniqeSetOfCharactersThatAreNotMyPassword_50kz5S99g2Q88bTi3ne"
/// unique ID of our listbox command
#define IDC_LISTBOX_ID 123
static LRESULT WINAPI wndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ){
switch(msg){
case WM_CREATE:{
HWND listboxHwnd= CreateWindow( "LISTBOX", NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_NOTIFY, 10, 10, 200, 100, hwnd, (HMENU)IDC_LISTBOX_ID, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 0" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 1" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 2" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 3" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 4" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 5" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 6" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 7" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 8" );
SendMessage( listboxHwnd, LB_ADDSTRING, 0, (LPARAM)"List Item 9" );
}break;
case WM_COMMAND:{
switch( LOWORD(wParam) ){
case IDC_LISTBOX_ID:{
switch(HIWORD(wParam)){
case LBN_SELCHANGE:{ /// user have selected item in our listbox
int id= SendMessage( (HWND)lParam, LB_GETCARETINDEX, 0, 0 ); /// id of seleted item, starting from 0
char text[]= "Item 0 selected";
text[5] += id; /// thats one way of converting int to string :D
MessageBox( NULL, text, "Debug", MB_OK );
}break;
}
}break;
}
}break;
case WM_DESTROY:{
::PostQuitMessage(0);
}break;
}
return DefWindowProc( hwnd, msg, wParam, lParam);
}
int WINAPI WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd ){
WNDCLASSEX wc= {
sizeof(WNDCLASSEX),
CS_CLASSDC,
wndProc,
0,
0,
hInstance,
LoadIcon( NULL, IDI_APPLICATION ),
LoadCursor( NULL, IDC_ARROW ),
(HBRUSH)(COLOR_WINDOW+0),
NULL,
CLASS_NAME,
NULL
};
if( !RegisterClassEx(&wc) ){
MessageBox( NULL, "Fail to register window class.", "Error - Keyboardlord", MB_ICONERROR );
return -2;
}
HWND hwnd= CreateWindow( CLASS_NAME, "App Browser - Keyboardlord", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 250, 150, NULL, NULL, hInstance, NULL );
if( hwnd==NULL ){
MessageBox( NULL, "Fail to create window", "Error - Keyboardlord", MB_ICONERROR );
return -3;
}
ShowWindow( hwnd, nShowCmd );
MSG msg;
while( 0 < GetMessage( &msg, NULL, 0, 0) ){
TranslateMessage( &msg );
DispatchMessage( &msg );
}
::DestroyWindow( hwnd );
::UnregisterClass( CLASS_NAME, hInstance );
return 0;
}

GetWindowText() in Win32 C++ is not working

following code is not working .i am trying to get text from edit control but it does not work.m tired by trying all possible codes looking documentation on msdn etc...
case WM_COMMAND:
switch(LOWORD(wParam)){
case 1:
::MessageBox(hwnd,"button clicked","message",MB_OK);
break;
case 2:
TCHAR t[20]; //
GetWindowText(text_box,t,19);// this is not working????????????????
::MessageBox(hwnd,t,t,MB_OK);
cout<<t;
break;
for refrence below is the complete code :
#include <windows.h>
#include<iostream>
using namespace std;
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND text_field, button , text_box;
char text_saved[20];
switch(msg)
{ case WM_CREATE:
text_field = CreateWindow("STATIC",
"Hello World",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,20, 90,25,
hwnd,
NULL,NULL,NULL);
button = CreateWindow("BUTTON",
"push button",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,50, 100,20,
hwnd,
(HMENU)1,NULL,NULL
) ;
text_box = CreateWindow("EDIT",
" ",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,80, 200,25,
hwnd,
NULL,NULL,NULL
);
CreateWindow("BUTTON",
"Save",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,120, 100,20,
hwnd,
(HMENU)2,NULL,NULL
);
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case 1:
::MessageBox(hwnd,"button clicked","message",MB_OK);
break;
case 2:
TCHAR t[20];
GetWindowText(text_box,t,19);
::MessageBox(hwnd,t,t,MB_OK);
cout<<t;
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500,500,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
You've defined text_box (and the other variables) as local to the WndProc function, meaning their values are lost every time that function is called to process a message. You need to move them outside of the function scope (or make them static) if you want to preserve their values from one message to the next.
This is a working reworked version of your code, replacing the local variable text_box (which doesn't retain information from one call to the next) with a numerical control id and use of GetDlgItem, changing from ANSI to Unicode text, and fixing some other stuff, while mainly keeping the formatting:
#undef UNICODE
#define UNICODE
#include <windows.h>
#include<iostream>
#include <string>
using namespace std;
namespace g {
const auto class_name = L"myWindowClass";
const auto push_button_id = 1;
const auto save_button_id = 2;
const auto edit_field_id = 3;
const auto h_instance = ::GetModuleHandle( nullptr );
} // namespace g
// Step 4: the Window Procedure
void create_controls( const HWND hwnd )
{
CreateWindow( L"STATIC",
L"Hello World",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,20, 90,25,
hwnd,
nullptr, g::h_instance, nullptr );
CreateWindow( L"BUTTON",
L"push button",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,50, 100,20,
hwnd,
(HMENU) g::push_button_id, g::h_instance, nullptr
) ;
CreateWindow( L"EDIT",
L"",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,80, 200,25,
hwnd,
(HMENU) g::edit_field_id, g::h_instance, nullptr
);
CreateWindow( L"BUTTON",
L"Save",
WS_VISIBLE | WS_CHILD | WS_BORDER,
20,120, 100,20,
hwnd,
(HMENU) g::save_button_id, g::h_instance, nullptr
);
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch(msg)
{
case WM_CREATE:
create_controls( hwnd );
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case 1:
::MessageBox( hwnd, L"button clicked", L"message", MB_SETFOREGROUND );
break;
case 2:
const HWND text_box = GetDlgItem( hwnd, g::edit_field_id );
const int n = GetWindowTextLength( text_box );
wstring text( n + 1, L'#' );
if( n > 0 )
{
GetWindowText( text_box, &text[0], text.length() );
}
text.resize( n );
::MessageBox(hwnd, text.c_str(), L"The text:", MB_SETFOREGROUND );
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int main()
{
//Step 1: Registering the Window Class
WNDCLASSEX wc = { sizeof( WNDCLASSEX ) };
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g::h_instance;
wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
wc.lpszMenuName = nullptr;
wc.lpszClassName = g::class_name;
wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(nullptr, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_SETFOREGROUND );
return E_FAIL;
}
// Step 2: Creating the Window
const HWND hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g::class_name,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500,500,
nullptr, nullptr, g::h_instance, nullptr);
if(hwnd == nullptr)
{
MessageBox(nullptr, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
return E_FAIL;
}
ShowWindow(hwnd, SW_SHOWDEFAULT); // Note: any other value is replaced.
UpdateWindow(hwnd); // Not strictly necessary.
// Step 3: The Message Loop
MSG Msg;
int get_message_result;
while( (get_message_result = GetMessage(&Msg, nullptr, 0, 0)) > 0 )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (get_message_result < 0? E_FAIL : Msg.wParam);
}

How to properly handle a win32 GUI message loop?

I'm making a simple text editor win32 application for fun. I'm having a peculiar problem with my program. It seems that my program is not returning zero when it exits. Instead, it is returning 1385929. When my main GUI window is destroyed, I use PostQuitMessage( 0 ), but it seems that is not what is being returned in my main function's message.wParam. Here is my code thus far,
#define WIDTH 500
#define HEIGHT 400
#define EDIT_ID 10
LRESULT CALLBACK windowProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
{
static HDC deviceContext = INVALID_HANDLE_VALUE;
static HWND editControl = INVALID_HANDLE_VALUE;
switch ( message )
{
case WM_CREATE :
deviceContext = GetDC( window );
if ( !deviceContext )
{
showWindowsError( "Creating Device Context", FALSE );
DestroyWindow( window );
}
editControl = CreateWindow(
"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL,
0,
0,
0,
0,
window,
( HMENU )EDIT_ID,
( HINSTANCE )GetWindowLong( window, GWL_HINSTANCE ),
NULL
);
if ( !editControl )
{
showWindowsError( "Creating Edit Control", TRUE );
DestroyWindow( window );
}
return 0;
break;
case WM_COMMAND :
switch ( wParam )
{
case WM_UNDO :
SendMessage( editControl, WM_UNDO, 0, 0 );
break;
case WM_CUT :
SendMessage( editControl, WM_CUT, 0, 0 );
break;
case WM_COPY :
SendMessage( editControl, WM_COPY, 0, 0 );
break;
case WM_PASTE :
SendMessage( editControl, WM_PASTE, 0, 0 );
break;
case WM_CLEAR :
SendMessage( editControl, WM_CLEAR, 0, 0 );
break;
default:
return DefWindowProc( window, message, wParam, lParam );
}
case WM_SIZE :
MoveWindow( editControl, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
return 0;
break;
case WM_DESTROY :
ReleaseDC( window, deviceContext );
DestroyWindow( editControl );
PostQuitMessage( 0 );
return 0;
break;
}
return DefWindowProc( window, message, wParam, lParam );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdArgs, int nCmdShow )
{
WNDCLASSEX windowClass = { 0 };
HWND window = INVALID_HANDLE_VALUE;
MSG message = { 0 };
HBRUSH windowColor = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
windowClass.cbSize = sizeof( windowClass );
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = windowProc;
windowClass.hInstance = hInstance;
windowClass.hCursor = LoadCursor( NULL, IDC_ARROW );
windowClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
windowClass.hbrBackground = windowColor;
windowClass.lpszClassName = "TextEditorWindow";
if ( !RegisterClassEx( &windowClass ) )
{
DeleteObject( windowColor );
showWindowsError( "Registering Windows Class", TRUE );
}
window = CreateWindow(
"TextEditorWindow",
"Text Editor",
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
WIDTH,
HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if ( !window )
{
DeleteObject( windowColor );
showWindowsError( "Creating GUI", TRUE );
}
ShowWindow( window, SW_SHOW );
UpdateWindow( window );
do
{
TranslateMessage( &message );
DispatchMessage( &message );
} while ( GetMessage( &message, window, 0, 0 ) > 0 );
DeleteObject( windowColor );
return message.wParam;
}
Your call to GetMessage() has the 2nd parameter set to your window's HWND, which limits the messages received only to those sent to that window - see the documentation of the API function.
WM_QUIT is, on the other hand, a message sent to the thread running the message pump, without any particular window. Because of that filter, you don't receive it and message.wParam is never set to that 0.
But why does the loop end and the program shuts down anyway? Because that HWND in window gets invalid after the window is closed, therefore GetMessage() ends with an error and returns -1.
Additionally, you are currently calling TranslateMessage() and DispatchMessage() with message before it is filled with any correct data, on the first iteration. The loop should rather be like this:
while ( GetMessage( &message, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &message );
DispatchMessage( &message );
}

How to use custom icons for toolbars in winapi programming

I'm trying to use my own custom images for creating a toolbar in a win32 winapi program. This is what I have ( in my WM_CREATE case ):
#define IDT_MAIN_TOOL 101
TBBUTTON tbb[ 1 ];
TBADDBITMAP tbab;
HWND hToolbar = CreateWindowEx( 0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT, 0, 0, 0, 0, hwnd, ( HMENU )IDT_MAIN_TOL, NULL, NULL );
SendMessage( hToolbar, TB_BUTTONSTRUCTSIZE, ( WPARAM )sizeof( TBBUTTON ), 0 );
tbab.hInst = HINST_COMMCTRL;
tbab.nID = IDB_HIST_LARGE_COLOR;
SendMessage( hToolbar, TB_ADDBITMAP, 0, ( LPARAM )&tbab );
ZeroMemory( tbb, sizeof( tbb ) );
tbb[ 0 ].iBitmap = HIST_BACK;
// I've also tried tbb[ 0 ].iBitmap = LoadIcon( NULL, "browse_back.ico" );
// However, iBitmap must be an integer and can't figure out how to use my 'browse_back.ico' image
tbb[ 0 ].fsState = TBSTATE_ENABLED;
SendMessage( hToolbar, TB_ADDBUTTONS, sizeof( tbb ) / sizeof( TBBUTTON ), ( LPARAM )&tbb );
I would like to use my own icon image: 'browse_back.ico' as the image for that toolbar button. How is this accomplished? Not sure if this is necessary but I'm using Microsoft Visual C++ 2010 Express.
Read the documentation:
iBitmap
Type: int
Zero-based index of the button image. Set this member to I_IMAGECALLBACK, and the toolbar will send the TBN_GETDISPINFO notification code to retrieve the image index when it is needed.
Version 5.81. Set this member to I_IMAGENONE to indicate that the button does not have an image. The button layout will not include any space for a bitmap, only text.
If the button is a separator, that is, if fsStyle is set to BTNS_SEP, iBitmap determines the width of the separator, in pixels. For information on selecting button images from image lists, see TB_SETIMAGELIST message.
So you need to create an image list using ImageList_Create(), add your ICO image to it using ImageList_Add() or ImageList_ReplaceIcon(), associate it with the toolbar using TB_SETIMAGELIST, and then you can set tbb[0].iBitmap to the ICO's index within the image list.
There are two ways that I know doing it. One is using TBADDBITMAP and the other one is using HIMAGELIST. In this example I use TBADDBITMAP but I personally prefer HIMAGELIST.
project.rc
#include "resource.h"
IDB_DOCUMENT BITMAP "document.bmp"
IDB_DRUGS BITMAP "drugs.bmp"
resource.h
#define IDTB_TOOLBAR 1000
#define IDB_DOCUMENT 1001
#define IDB_DRUGS 1002
#define ID_ADD_NEW 2000
tb.c
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
const char ClassName[] = "ToolbarExample";
HWND hWndToolBar;
HINSTANCE g_hInstance;
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CREATE:
{
TBADDBITMAP tbab1, tbab2;
TBBUTTON tbb[2];
hWndToolBar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd,
(HMENU)IDTB_TOOLBAR, g_hInstance, NULL);
if (!hWndToolBar)
{
MessageBox(NULL, "ToolBar Failed.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
SendMessage(hWndToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hWndToolBar, TB_SETBITMAPSIZE, (WPARAM)0, (LPARAM)MAKELONG(32, 32));
// Add Bitmaps
tbab1.hInst = g_hInstance;
tbab1.nID = IDB_DOCUMENT;
SendMessage(hWndToolBar, TB_ADDBITMAP, (WPARAM) 1, (LPARAM) &tbab1);
tbab2.hInst = g_hInstance;
tbab2.nID = IDB_DRUGS;
SendMessage(hWndToolBar, TB_ADDBITMAP, (WPARAM) 1, (LPARAM) &tbab2);
// Add Buttons
ZeroMemory(tbb, sizeof(tbb));
tbb[0].iBitmap = 0; // The index of the bitmap on toolbar bitmap collection
tbb[0].idCommand = ID_ADD_NEW;
tbb[0].fsState = TBSTATE_ENABLED;
tbb[0].fsStyle = TBSTYLE_BUTTON;
tbb[0].iString = SendMessage(hWndToolBar, TB_ADDSTRING, 0, (LPARAM)TEXT("Add New"));
tbb[1].iBitmap = 1;
tbb[1].idCommand = 0;
tbb[1].fsState = TBSTATE_ENABLED;
tbb[1].fsStyle = TBSTYLE_BUTTON;
tbb[1].iString = SendMessage(hWndToolBar, TB_ADDSTRING, 0, (LPARAM)TEXT("Drugs"));
SendMessage(hWndToolBar, TB_ADDBUTTONS, sizeof(tbb) / sizeof(TBBUTTON), (LPARAM)&tbb);
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case ID_ADD_NEW:
{
MessageBox(NULL, "Toolbar Button One", "Success", MB_OK | MB_ICONINFORMATION);
}
break;
}
return 0;
}
break;
case WM_SIZE:
SendMessage(hWndToolBar, TB_AUTOSIZE, 0, 0);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, Msg, wParam, lParam));
}
return 0;
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
InitCommonControls();
g_hInstance = hInstance;
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName;
if (!RegisterClass(&wc))
{
MessageBox(NULL, "Failed To Register The Window Class.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
HWND hWnd;
hWnd = CreateWindow(ClassName, "Toolbars", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL, "Window Creation Failed.", "Error", MB_OK | MB_ICONERROR);
return 0;
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}