Add toolbar Dialogbox with Win32 API - winapi

I have a dialog box on which controls are added with resource editor. But I am trying to create a toolbar on the fly in WM_INITGDIALOG message but the toolbar is not visible. Is there something else to do make it visible(I dont think so but...). If this is not possible how can add a toolbar in resource editor.
As you guessed I use VS 2008.
CreateButtons(HWND hwnd)
{
HIMAGELIST m_hTBImageList;
HIMAGELIST m_hTBHottrack;
HWND hwndSysButtonTB = CreateWindowEx(0,
TOOLBARCLASSNAME,
_T(""),
WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NORESIZE | CCS_NOPARENTALIGN,
toolbarRect.left, toolbarRect.top, toolbarRect.right-toolbarRect.left, toolbarRect.bottom-toolbarRect.top,
hwnd,
(HMENU)IDR_TOOLBAR,
(HINSTANCE)hAppInstance,
NULL);
m_hTBImageList = ImageList_LoadImage((HINSTANCE)hAppInstance,
MAKEINTRESOURCE(IDB_BITMAP_ICONS), toolbarButtonSize.cx, 1,
0, IMAGE_BITMAP, LR_CREATEDIBSECTION|LR_SHARED);
m_hTBHottrack = ImageList_LoadImage((HINSTANCE)hAppInstance,
MAKEINTRESOURCE(IDB_MOUSEOVER), toolbarButtonSize.cx, 1,
0, IMAGE_BITMAP, LR_CREATEDIBSECTION|LR_SHARED);
SendMessage(hwndSysButtonTB, (UINT) TB_SETIMAGELIST, 0, (LPARAM)m_hTBImageList);
SendMessage(hwndSysButtonTB, (UINT) TB_SETHOTIMAGELIST, 0, (LPARAM)m_hTBHottrack);
SendMessage(hwndSysButtonTB, (UINT) TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
// win2k: set color of hot tracking frame
COLORSCHEME scheme;
scheme.dwSize = sizeof(scheme);
scheme.clrBtnHighlight = RGB(175,175,175);
scheme.clrBtnShadow = RGB(175,175,175);
SendMessage(hwndSysButtonTB, (UINT) TB_SETCOLORSCHEME, 0, (LPARAM)&scheme);
TBBUTTON ButtonEnd = {0,ID_BUTTON_END,TBSTATE_ENABLED,TBSTYLE_BUTTON};
TBBUTTON ButtonRefresh = {1,ID_BUTTON_REFRESH,TBSTATE_ENABLED,TBSTYLE_BUTTON};
TBBUTTON ButtonOptions = {2,ID_BUTTON_PROPERTIES,TBSTATE_ENABLED,TBSTYLE_BUTTON};
SendMessage(hwndSysButtonTB, (UINT) TB_ADDBUTTONS, 1, (LPARAM)&ButtonEnd);
SendMessage(hwndSysButtonTB, (UINT) TB_ADDBUTTONS, 1, (LPARAM)&ButtonRefresh);
SendMessage(hwndSysButtonTB, (UINT) TB_ADDBUTTONS, 1, (LPARAM)&ButtonOptions);
}

You have to call
SendMessage(hwndSysButtonTB, TB_AUTOSIZE, 0, 0);
ShowWindow(hwndSysButtonTB , SW_SHOW);
at the end of your function.
And I think you should use an TBBUTTON array instead of three separate variables. Then you can add them all at once with
SendMessage(hwndSysButtonTB, (UINT) TB_ADDBUTTONS, 3, (LPARAM)&ButtonArray);

Related

Draw cursor multiple display (only draw text icon) GDI

I select displays in multiple display environments and produce captured programs.
And try to draw a cursor by selecting dc among multiple displays.
I draw cursors with bitblt bitmap images and it works well.
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
But When I select from createDC multuple display value,
DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME);
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL);
I am working hard to get other display images. But there is no drawing cursor. (Other forms of cursor are not drawn, only text cursor is drawn)
This is my code.
const int d_count = GetSystemMetrics(SM_CMONITORS); //I have 3 display and count is 3.
HDC hCaptureDC;
HDC HDCC;
HBITMAP hBitmap;
HGDIOBJ hOld;
BYTE *src;
bool GetMouse() {
CURSORINFO cursor = { sizeof(cursor) };
::GetCursorInfo(&cursor);
ICONINFOEXW info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
BITMAP bmpCursor = { 0 };
GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);
POINT point;
GetCursorPos(&point);
bool res = DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight, 0, NULL, DI_NORMAL);
return res;
}
void screencap(){
BITMAPINFO MyBMInfo;
BITMAPINFOHEADER bmpInfoHeader;
HWND m_hWndCopy= GetDesktopWindow();
GetClientRect(m_hWndCopy, &ImageRect);
const int nWidth = ImageRect.right - ImageRect.left;
const int nHeight = ImageRect.bottom - ImageRect.top;
MyBMInfo = { 0 };
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
bmpInfoHeader = { sizeof(BITMAPINFOHEADER) };
bmpInfoHeader.biWidth = nWidth;
bmpInfoHeader.biHeight = nHeight;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 32;
b_size = ((nWidth * bmpInfoHeader.biBitCount + 31) / 32) * 4 * nHeight;
//HDCC = CreateDC((L"Display"), NULL, NULL, NULL); //It's good.
DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME);
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL); // It draws only text cursor.
hCaptureDC = CreateCompatibleDC(HDCC);
hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, 0, 0, SRCCOPY);
GetMouse();
SelectObject(hCaptureDC, hOld);
src = (BYTE*)malloc(b_size);
if (GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)) {
if (RGBSaveBMP(src) == true)
free(src);
}
}
I'm using windows 10.
How can I solved?
Any links, idea, Thanks.
ADD
It does not draw cursor....(except text cursor.)
HDCC = CreateDC(TEXT("\\\\.\\Display1"), NULL, NULL, NULL);
It draws cursor..
HDCC = CreateDC(TEXT("Display"), NULL, NULL, NULL);
SOLVED:
Now, I changed my algorithm.
CreateDC(L"Display", NULL, NULL, NULL) create DC for all monitors, so what is your problem? – user2120666 Apr 22 at 15:37
This comment is very helpful but It was not kind. (Or I was stupid.) :(
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
HDCC has "All Virtual Screens" DC.
When I selected the monitor I needed, and accordingly selected and used the area to capture on the virtual screen.
HDC hCaptureDC = CreateCompatibleDC(HDCC);
HBITMAP hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
DEVMODE dev;
std::string str = "\\\\.\\Display" + std::to_string(select);
std::wstring temp;
temp.assign(str.begin(), str.end());
EnumDisplaySettingsW(temp.c_str(), ENUM_CURRENT_SETTINGS, &dev);
printf("Display%d : (%d * %d) (%d, %d)\n", select, dev.dmPelsWidth, dev.dmPelsHeight, dev.dmPosition.x, dev.dmPosition.y);
nWidth = dev.dmPelsWidth;
nHeight = dev.dmPelsHeight;
nposx = dev.dmPosition.x;
nposy = dev.dmPosition.y;
hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, nposx, nposy, SRCCOPY);
int colorcheck = GetSystemMetrics(SM_SAMEDISPLAYFORMAT);
CURSORINFO cursor = { sizeof(cursor) };
bool check = ::GetCursorInfo(&cursor);
bool check2 = ::GetCursorInfo(&cursor);
int count = ShowCursor(TRUE);
info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
GetCursorPos(&point);
if (point.x > nWidth) {
point.x = point.x - nWidth;
}
else if (point.x < 0) {
point.x = nWidth + point.x;
}
if (point.y > nHeight) {
point.y = point.y - nHeight;
}
else if (point.y < 0) {
point.y = nHeight + point.y;
}
cursor.ptScreenPos.x = point.x;
cursor.ptScreenPos.y = point.y;
bool res = ::DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, 0, 0, 0, NULL, DI_NORMAL);
BYTE* src = (BYTE*)malloc(b_size);
GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)
Thanks for the comment!
Your call GetClientRect(m_hWndCopy, &ImageRect); is wrong.
From documentation:
The rectangle of the desktop window returned by GetWindowRect or
GetClientRect is always equal to the rectangle of the primary monitor,
for compatibility with existing applications.
So you are capturing only primary display.
Following MSDN to get EnumDisplayMonitor may solve your problem.
Use EnumDisplayMonitors to get the device name and pass it to
CreateDC.

CreateWindow by CLSID and QueryInterface it in Win32

I want to create a COM control in Win32 by clsid: {3523C2FB-4031-44E4-9A3B-F1E94986EE7F} and then use the api QueryInterface to send commands to it. In MFC project this would be very simple in 4 lines of code:
m_wndMsTsc.CreateControl(L"{3523C2FB-4031-44E4-9A3B-F1E94986EE7F}", NULL, WS_VISIBLE, CRect(10, 10, 470, 280), this,0))
LPUNKNOWN lpUnk = m_wndMsTsc.GetControlUnknown();
lpUnk->QueryInterface(IID_IMsRdpClient5, (void**)&m_pMsTsc);
lpUnk->QueryInterface(IID_IMsRdpClientNonScriptable5, (void**)&pns);
In Win32 what i tried so far:
container = ::CreateWindow(L"EDIT",L"", WS_CHILD | WS_VISIBLE, 0, 0, rect.right, rect.bottom, mainWindow, 0, hInstance, 0);
IMsRdpClient5 *rdpClient = NULL;
// Then initialize com control
CoInitialize(0);
CoCreateInstance(CLSID_MsRdpClient5, 0, CLSCTX_ALL, IID_IMsRdpClient5, (void**)&rdpClient);
// Attach
AtlAxAttachControl(rdpClient, container, 0);
IUnknown *pUnk = NULL;
AtlAxGetControl(container, &pUnk);
pUnk->QueryInterface(IID_IMsRdpClient5, (void**)&rdpClient);
A very basic example how to create a control by clsid and attach it to IUnknown would be very helpful!
HRESULT hr = AtlAxWinInit();
HWND hWnd = CreateWindow(_T("AtlAxWin"), _T("{3523C2FB-4031-44E4-9A3B-F1E94986EE7F}"), WS_CHILD | WS_VISIBLE, 10, 10, 400, 300, hwnd, (HMENU)102, NULL, NULL);
IUnknown *unkn;
hr = AtlAxGetControl(hWnd, &unkn);
unkn->QueryInterface(IID_IMsRdpClient5, (void**)&rdpClient);
unkn->QueryInterface(IID_IMsRdpClientNonScriptable5, (void**)&rdpClientNonScriptable);\
This method works perfectly in Win32. Thanks everyone for ideas

Detect Button Press in Tab Page

I am using the WinAPI to create a GUI utility. I have two Tabs and each tab has some buttons. I am creating the buttons with this function:
CreateWindowEx(NULL,"button", "Clear", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
150, 175, 100, 25, tab_window_2, (HMENU) CLEAR_DATA, instance_handle, NULL);
In the Windows proc function, I don't know how to detect when the above button is pressed. I also tried handling CLEAR_DATA in the WM_COMMAND switch construct, as follows.
switch ( message ) {
case WM_COMMAND:{
switch(LOWORD(wparam)) {
case CLEAR_DATA : break
}
}
How can I detect and handle those buttons being pressed?
I am creating the tab_window_2 tab as follows :
class frame_window {
private:
LPCSTR window_class_name;
HINSTANCE instance_handle;
HCURSOR cursor_arrow;
HWND window_handle;
HWND tab_handle;
HWND tab_window_1;
HWND tab_window_2;
HWND current_tab_window;
RECT client_rectangle;
public:
frame_window(LPCSTR window_class_identity) : window_class_name(window_class_identity) {
INITCOMMONCONTROLSEX common_controls;
common_controls.dwSize = sizeof(INITCOMMONCONTROLSEX);
common_controls.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx(&common_controls);
int screen_width = GetSystemMetrics(SM_CXFULLSCREEN);
int screen_height = GetSystemMetrics(SM_CYFULLSCREEN);
instance_handle = GetModuleHandle(NULL);
WNDCLASS window_class = { CS_OWNDC, main_window_proc, 0, 0,
instance_handle, NULL,
NULL, NULL, NULL,
window_class_name };
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Create a standard frame window
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
RegisterClass(&window_class);
window_handle = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
window_class_name,
"IR Remote and Barcode Demo",
WS_OVERLAPPEDWINDOW |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
100, 100, screen_width-1600,
screen_height-490, NULL, NULL,
instance_handle, NULL);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Get the size of the client rectangle for the window we have just created
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
RECT client_rect;
GetClientRect(window_handle, &client_rect);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Create the tab control window.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tab_handle = CreateWindowEx(NULL, WC_TABCONTROL, NULL,
WS_CHILD | WS_VISIBLE,
10, 10, client_rect.right-client_rect.left-20,
client_rect.bottom-client_rect.top-10,
window_handle, NULL,
instance_handle, NULL);
// Create three tabs.
TCITEM tab_info;
memset(&tab_info, 0, sizeof(tab_info));
tab_info.mask = TCIF_TEXT;
tab_info.pszText = "tab#1";
tab_info.cchTextMax = 5;
SendMessage(tab_handle, TCM_INSERTITEM, 0, (LPARAM)&tab_info);
tab_info.pszText = "tab#2";
SendMessage(tab_handle, TCM_INSERTITEM, 1, (LPARAM)&tab_info);
RECT tab_rectangle;
GetClientRect(tab_handle, &tab_rectangle);
SendMessage(tab_handle, TCM_ADJUSTRECT, FALSE, (LPARAM)&tab_rectangle);
// Create the tab view windows
tab_window_1 = CreateWindowEx(NULL, "STATIC", " ",
WS_CHILD | WS_VISIBLE|SS_OWNERDRAW,
tab_rectangle.left+10, tab_rectangle.top+10,
tab_rectangle.right-tab_rectangle.left,
tab_rectangle.bottom -tab_rectangle.top,
tab_handle, (HMENU)1,
instance_handle, NULL);
SetParent(tab_window_1, window_handle);
current_tab_window = tab_window_1;
tab_window_2 = CreateWindowEx(NULL, "STATIC", " ",
WS_CHILD|SS_OWNERDRAW,
tab_rectangle.left+10, tab_rectangle.top+10,
tab_rectangle.right-tab_rectangle.left,
tab_rectangle.bottom -tab_rectangle.top,
tab_handle, (HMENU)2,
instance_handle, NULL);
CreateWindowEx(NULL,"button", "Clear", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
150, 175, 100, 25, tab_window_2, (HMENU) CLEAR_DATA, instance_handle, NULL);
SetParent(tab_window_2, window_handle);
SetCursor(LoadCursor(NULL, IDC_ARROW));
SetWindowLongPtr(window_handle, GWL_USERDATA, (LONG)this);
ShowWindow(window_handle, SW_SHOW);
UpdateWindow(window_handle);
}
~frame_window() {
UnregisterClass(window_class_name, instance_handle);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Windows main entry point
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int WINAPI wWinMain(HINSTANCE instance_handle, HINSTANCE, LPWSTR, INT) {
frame_window main_window("my base window");
main_window.run();
return 0;
}
The WM_COMMAND for handling the events from a Push Button must be in the Window Procedure of it's parent. Your code show tab_window_2 as the parent for the CLEAR_DATA button.
Move the WM_COMMAND code in the right Window Proc (or Dialog Proc).
EDIT: I think you didn't understand how the Tab Control works.
If you want each Tab View to contain more than a dummy static control, you should use modeless and borderless DialogBox, children of the Tab Control, and show/hide them accordingly to the TCN_SELCHANGE notification.
If you don't realy need the Dialog Box functionalities, you could create regular child windows (with RegisterClass/CreateWindow) and then add your controls as child windows.
In either case, the show/hide code must react to TCN_SELCHANGE.
With regular child windows or with Dialog Box the net effect is the same: you will have a Window Procedure, or a Dialog Procadure, in which WM_COMMAND will deal with user actions.
Don't play with SetParent. But, if you absolutly want it, then use:
HWND hWndPushClear = CreateWindowEx(NULL,"button", "Clear", [...]
SetParent( hWndPushClear, window_handle );
You may have weird Paint/Focus problems, however.
EDIT: Unfortunately, it seems that there is no good Tab Control tutorial in line.
I recommend updating your actual source code. As a starting point, do the following:
Replace CreateWindowEx by CreateDialog for tab_window_1 end tab_window_2 (only one Dialog must be visible)
Suppress all SetParent calls
Your CreateWindowEx() and WM_COMMAND code are seems correct.
So,
Check return value of CreateWindowEx() whether is NULL. NULL means which is failed to create control.
Check HWND of parent is valid. In your code, it is tab_window_2.
Also, if you do not want to any WS_EX_XXX style, you can just use CreateWindow().
This code is just sample.
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
switch(iMessage) {
case WM_CREATE:
CreateWindow("button","Clear",WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
20,20,100,25,hWnd,(HMENU)0,g_hInst,NULL);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 0:
MessageBox(hWnd,"Clear Button Clicked","Button",MB_OK);
break;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

creating rebar control and introduction a band with toolbar into the rebar

I use this code to create a rebar control, and introduction a band with toolbar into the rebar.
But when window is shown up, I can not see the toolbar. and when I check the height of the rebar, in this line of code: int height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; I find rebar's height is only 4 pixels.
#include <windows.h>
#include <stdlib.h>
#include <CommCtrl.h>
#pragma comment(lib, "comctl32.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE instance;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
instance = hInstance;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"Example";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
RegisterClassEx(&wcex);
HWND hWnd = CreateWindow(L"Example", L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
500, 500, NULL, NULL, hInstance, NULL);
// Initialize common controls.
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
HWND hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
0, 0, 100, 50, hWnd, NULL, instance, NULL);
// create toolbar
HWND hWndToolbar = CreateWindowEx(0 , TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_TOOLTIPS,
0, 0, 0, 0, hwndRebar, (HMENU)0, instance, NULL);
HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, 3, 0);
SendMessage(hWndToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList);
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
TBBUTTON tbb[4] =
{
{0,0,TBSTATE_ENABLED,TBSTYLE_BUTTON},
{1,1,TBSTATE_ENABLED,TBSTYLE_BUTTON},
{2,2,TBSTATE_ENABLED,TBSTYLE_BUTTON},
};
SendMessage(hWndToolbar, (UINT) TB_ADDBUTTONS, 3, (LPARAM)&tbb);
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar , SW_SHOW);
// Initialize band info.
REBARBANDINFO rbBand = { sizeof(REBARBANDINFO) };
rbBand.fMask = RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_COLORS;
rbBand.fStyle = RBBS_GRIPPERALWAYS;
// Get the height of the toolbar.
DWORD dwBtnSize = (DWORD)SendMessage(hWndToolbar, TB_GETBUTTONSIZE, 0,0);
// Set values unique to the band with the toolbar.
rbBand.clrFore = RGB(233, 233, 233);
rbBand.clrBack = RGB(200, 200, 200);
rbBand.lpText = TEXT("");
rbBand.hwndChild = hWndToolbar;
rbBand.cyChild = LOWORD(dwBtnSize);
rbBand.cyMinChild = LOWORD(dwBtnSize);
rbBand.cxMinChild = 3 * HIWORD(dwBtnSize);
// The default width is the width of the buttons.
rbBand.cx = 0;
// Add the band
SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
// show the main window
ShowWindow(hWnd, nCmdShow);
// check the rebar size
WINDOWPLACEMENT wp;
GetWindowPlacement(hwndRebar, &wp);
int height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
As follows from the comments, the solution was:
REBARBANDINFO rbBand;
rbBand.cbSize = REBARBANDINFO_V3_SIZE;
// initialize the rest here
This seems to affect older versions of Windows (specifically, XP), because the original code compiles and runs fine on Windows 7.
This was mentioned in the comments to a MSDN page: http://msdn.microsoft.com/en-us/library/windows/desktop/bb774393.aspx
As was already stated, the cbSize member of the REBARBANDINFO struct needed to be set.
Note the following about the provided code as well:
The images on the toolbar buttons don't show up. Right after creating the image list you have to make the following call to load the images:
SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
The TBBUTTON array is declared with a size of 4 but it only gets populated with 3 items. Technically it should be declared as:
TBBUTTON tbb[3]

create toolbar with my bitmap images

this is an example code of msdn to create toolbar, but this example use the standard images of the system.
What do I need to change in this code to use my images from resource file, for example: IDB_COPY BITMAP "copy.bmp", and IDB_CUT BITMAP "cut.bmp", and IDB_PASTE BITMAP "paste.bmp".
HIMAGELIST g_hImageList = NULL;
HWND CreateSimpleToolbar(HWND hWndParent)
{
// Declare and initialize local constants.
const int ImageListID = 0;
const int numButtons = 3;
const int bitmapSize = 16;
const DWORD buttonStyles = BTNS_AUTOSIZE;
// Create the toolbar.
HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
hWndParent, NULL, g_hInst, NULL);
if (hWndToolbar == NULL)
return NULL;
// Create the image list.
g_hImageList = ImageList_Create(bitmapSize, bitmapSize, // Dimensions of individual bitmaps.
ILC_COLOR16 | ILC_MASK, // Ensures transparent background.
numButtons, 0);
// Set the image list.
SendMessage(hWndToolbar, TB_SETIMAGELIST,
(WPARAM)ImageListID,
(LPARAM)g_hImageList);
// Load the button images.
SendMessage(hWndToolbar, TB_LOADIMAGES,
(WPARAM)IDB_STD_SMALL_COLOR,
(LPARAM)HINST_COMMCTRL);
// Initialize button info.
// IDM_NEW, IDM_OPEN, and IDM_SAVE are application-defined command constants.
TBBUTTON tbButtons[numButtons] =
{
{ MAKELONG(STD_FILENEW, ImageListID), IDM_NEW, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"New" },
{ MAKELONG(STD_FILEOPEN, ImageListID), IDM_OPEN, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Open"},
{ MAKELONG(STD_FILESAVE, ImageListID), IDM_SAVE, 0, buttonStyles, {0}, 0, (INT_PTR)L"Save"}
};
// Add buttons.
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
// Resize the toolbar, and then show it.
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar, TRUE);
return hWndToolbar;
}
I found this solution:
const int ID_TB_STANDARD = 0;
const int ID_IL_STANDARD = 0;
HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_TOOLTIPS, 0, 0, 0, 0, hWnd, (HMENU)ID_TB_STANDARD, hInstance, NULL);
HIMAGELIST hImageList = ImageList_LoadBitmap(hInstance, MAKEINTRESOURCEW(IDB_CUT), 16, 0, RGB(255, 0, 255));
ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_COPY)), NULL);
ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PASTE)), NULL);
SendMessage(hWndToolbar, TB_SETIMAGELIST, (WPARAM)ID_IL_STANDARD, (LPARAM)hImageList);
SendMessage(hWndToolbar, (UINT) TB_SETHOTIMAGELIST, 0, (LPARAM)hHotImageList);
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
TBBUTTON tbb[3] =
{
{0,ID_CUT,TBSTATE_ENABLED,TBSTYLE_BUTTON},
{1,ID_COPY,TBSTATE_ENABLED,TBSTYLE_BUTTON},
{2,ID_PASTE,TBSTATE_ENABLED,TBSTYLE_BUTTON},
};
SendMessage(hWndToolbar, (UINT) TB_ADDBUTTONS, 3, (LPARAM)&tbb);
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar , SW_SHOW);

Resources