Some help?

Hello everybody,
I'm trying to develop a simple app with WinAPI, and I've already created the main window
and the menus, but when I create the toolbar I get only empty buttons, without images.
Here is my code:

(main.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <Windows.h>
#include <CommCtrl.h>
#include <cstring>
#include "resource.h"

//per lo stile dei controlli (per essere sicuri che venga caricata la versione 6 di ComCtl32.dll)
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' \
		""version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
//per evitare warning inutili sulle funzioni "deprecate"...
#pragma warning(disable: 4996)

HINSTANCE hInst;
char titolo[64] = {0};
const int NTASTI = 7;
void errore(const char *str);
LRESULT CALLBACK msgProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdSow)
{

	MSG msg;
	HWND hWnd;
	WNDCLASSEX wndCls;
	LPCTSTR clsName = "MyApp";
	
	hInst = hInstance;

	LoadString(hInstance, IDS_NOME_APP, titolo, 64);
	
	wndCls.cbSize = sizeof(WNDCLASSEX);								//dimensione di questa struttura
	wndCls.style = CS_HREDRAW | CS_VREDRAW;							//stile
	wndCls.lpfnWndProc = msgProc;									//messaggi
	wndCls.cbClsExtra = 0;											//memoria extra in compilazione
	wndCls.cbWndExtra = 0;											//memoria extra a rum-time
	wndCls.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICONA));	//icona
	wndCls.hCursor = LoadCursor(hInstance,
								MAKEINTRESOURCE(IDC_CURSORE1));		//cursore
	wndCls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);	//colore di sfondo
	wndCls.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);				//menu
	wndCls.lpszClassName = clsName;									//"classe"
	wndCls.hInstance = hInstance;									//istanza
	wndCls.hIconSm = LoadIcon(hInstance,
							MAKEINTRESOURCE(IDI_ICONA));			//icona (piccola)

	//registrazione della classe
	RegisterClassEx(&wndCls);
	
	//creazione della finestra
	hWnd = CreateWindow(clsName, titolo,
						WS_OVERLAPPEDWINDOW,
						CW_USEDEFAULT, CW_USEDEFAULT,
						CW_USEDEFAULT, CW_USEDEFAULT,
						NULL, NULL, hInstance, NULL);
	
	//controlla se la finestra è stata creata
	if(!hWnd)
		errore("Impossibile creare la finestra");

	//inizializza i controlli comuni
	INITCOMMONCONTROLSEX initCmmCrtl;
	initCmmCrtl.dwSize = sizeof(INITCOMMONCONTROLSEX);
	initCmmCrtl.dwICC = ICC_BAR_CLASSES;
	if(InitCommonControlsEx(&initCmmCrtl) == FALSE)
		errore("Impossibile inizializzare i controlli comuni");

	//crea la toolbar
	TBBUTTON tbrButtons[7] = {
	{0, IDM_FILE_NUOVO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0, 0},
	{1, IDM_FILE_APRI, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0, 0},
	{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0, 0},
	{2, IDM_FRECCIA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0, 0},
	{3, IDM_LINEA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0, 0},
	{4, IDM_RETTANGOLO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0, 0},
	{5, IDM_ELLISSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0, 0}};

	TBADDBITMAP tbrBitmap = {0};
	tbrBitmap.hInst = hInst;
	tbrBitmap.nID = IDB_TOOLBAR;

	HWND hWndTbr = CreateToolbarEx(hWnd, (WS_VISIBLE | WS_CHILD | TBSTYLE_WRAPABLE), 0, NTASTI, hInst,
								(UINT_PTR)LoadImage(hInst, MAKEINTRESOURCE(IDB_TOOLBAR), IMAGE_BITMAP, 0, 0, LR_VGACOLOR),
								tbrButtons, NTASTI, 16, 16, 16, 16, sizeof(TBBUTTON));
	if(hWndTbr == NULL)
		errore("Impossibile creare la toolbar");

	SendMessage(hWndTbr, TB_ADDBITMAP, 7, (LPARAM)&tbrBitmap);

	//mostra la finestra
	ShowWindow(hWnd, SW_SHOWNORMAL);
	UpdateWindow(hWnd);

	//gestione dei messaggi
	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	
	return msg.wParam;
}

LRESULT CALLBACK msgProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uiMsg)
	{
		case WM_DESTROY:
			PostQuitMessage(WM_QUIT);
			break;
		default:
			return DefWindowProc(hWnd, uiMsg, wParam, lParam);
	}
	return 0;
}

//stampa un messaggio di errore (se NDEBUG non è definita) e esce
void errore(const char *str)
{
#ifndef NDEBUG
	char msg[256] = {0};
	strcat(msg, str);
	strcat(msg, "\nCodice di errore: 0x");
	char numErr[64] = {0};
	itoa(GetLastError(), numErr, 16);
	strcat(msg, numErr);
#else
	char msg[256] = str;
#endif
	MessageBox(NULL, msg, "Errore", MB_OK | MB_ICONERROR);
	exit(-1);
}



(resource.h)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define IDC_CURSORE1                     100
#define IDI_ICONA                        101
#define IDS_NOME_APP                     102
#define IDM_FRECCIA                      103
#define IDM_LINEA                        104
#define IDM_RETTANGOLO                   105
#define IDM_ELLISSE                      106
#define IDR_MENU                         1000
#define IDM_FILE_NUOVO                   40000
#define IDM_FILE_APRI                    40001 
#define IDM_FILE_ESCI                    40002
#define IDM_INFO_INFO                    40003
#define IDB_TOOLBAR                      1001


(resource.rc)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "resource.h"

//cursore e icona
IDC_CURSORE1             CURSOR                  "cursore1.cur"
IDI_ICONA                ICON                    "bicchiere.ico"

//menu
IDR_MENU MENU
BEGIN
    POPUP "&File"
	BEGIN
	    MENUITEM "&Nuovo", IDM_FILE_NUOVO
		MENUITEM "&Apri", IDM_FILE_APRI
		MENUITEM SEPARATOR
	    MENUITEM "&Esci", IDM_FILE_ESCI
	END

	POPUP "&?"
	BEGIN
	    MENUITEM "&Info", IDM_INFO_INFO
	END
END

//stringhe
STRINGTABLE
BEGIN
    IDS_NOME_APP, "WinAPI - risorse"
	IDM_FILE_NUOVO, "Apre un nuovo file"
	IDM_FILE_APRI, "Apre un file"
	IDM_FILE_ESCI, "Esce"
	IDM_FRECCIA, "Nessuna azione selezionata"
	IDM_LINEA, "Traccia una linea"
	IDM_RETTANGOLO, "Disegna un rettangolo"
	IDM_ELLISSE, "Disegna un ellisse"
END

IDB_TOOLBAR BITMAP "toolbar.bmp"


Please help!!!
(I'm developing with visual studio 2012)
You should use "GetLastError()" and dump the error number to a file or something so that we know where it is failing.
You mean that I should call GetLastError() in all the places where there may be an error?
Yes. Check LoadImage() on line 80 and SendMessage() in line 86 if it fails.
I modified lines 80-86 to
1
2
3
4
5
6
7
8
9
10
11
12
13

	HANDLE hBitmap = LoadImage(hInst, MAKEINTRESOURCE(IDB_TOOLBAR), IMAGE_BITMAP, 0, 0, LR_VGACOLOR);
	if(hBitmap == NULL)
		errore("Impossibile caricare l'immagine della bitmap");

	HWND hWndTbr = CreateToolbarEx(hWnd, (WS_VISIBLE | WS_CHILD | TBSTYLE_WRAPABLE), 0, NTASTI, hInst,
								(UINT_PTR)hBitmap, tbrButtons, NTASTI, 16, 16, 16, 16, sizeof(TBBUTTON));
	if(hWndTbr == NULL)
		errore("Impossibile creare la toolbar");

	if(SendMessage(hWndTbr, TB_ADDBITMAP, 7, (LPARAM)&tbrBitmap) == -1)
		errore("SendMessage() ha fallito");


I tried this code and I got the toolbar with black icons.

Please note that I already call GetLastError() in errore() and append the error code to the string I use in the MessageBox().

EDIT:
I've also added this line at the top of main.cpp:
 
#pragma comment(lib, "comctl32.lib") 

Last edited on
Please read very carefully CreateToolbarEx documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb787469(v=vs.85).aspx

Try this without using LoadImage:
1
2
3
4
5
6
7
8
9
10
11
12
HWND hWndTbr = CreateToolbarEx(hWnd,

 WS_VISIBLE | WS_CHILD | TBSTYLE_WRAPABLE,
 0,
 NTASTI,

 hInst,
								
MAKEINTRESOURCE(IDB_TOOLBAR),
 tbrButtons,
 NTASTI,
 16, 16, 16, 16, sizeof(TBBUTTON));
I had to use
 
(UINT_PTR)MAKEINTRESOURCE(IDB_TOOLBAR)

instead of
 
MAKEINTRESOURCE(IDB_TOOLBAR)

but I got the same result: black icons.

Can it be because of an error in my resource file?

EDIT:
I got the same result removing the SendMessage() part
Last edited on
As long as your Resource.rc file is inside your project, there should be no errors.
If there is an error in the file, compilation fails.
But if it's not CreateToolbarEX(), SendMessage() or the resource file, what is it?
I don't know...
Found!

Well, not really...

I use SetLastError(0) to reset the error codes just before the call to CreateToolbarEx(), and I get the last error with GetLastError() just after this call.
I got 0x6 (ERROR_INVALID_HANDLE). It seems like it cannot find my resource or something else...

If you know how can I solve this, please send it.
There is no Remarks section (the commonly GetLastError return values are mostly under the Remarks section) on the MSDN but I noticed this:

MSDN wrote:
This function is deprecated, because it does not support all features of toolbars. Use CreateWindowEx instead. For examples, see Using Toolbar Controls.


It links back to:

http://msdn.microsoft.com/en-us/library/windows/desktop/bb760446(v=vs.85).aspx

It does not really look so hard.
I tried also with CreateWindowEx() but I got only black icons. I send three messages to the toolbar: TB_BUTTONSTRUCTSIZE, TB_ADDBITMAP and TB_ADDBUTTONS.
This is kinda weird, I don't know how can I help you...
If just you was not on the VS 2012... VS10 can not read those projects, I think, or I'd ask you to upload your project to some zip somewhere.
We may try to import it...
If you want I can upload it
Topic archived. No new replies allowed.