Trying to create HIMAGELIST, what am I doing wrong here? - c++

I want to create an HIMAGELIST for the list view. It actually needs to consist of file icons.
Here's the code I have:
HIMAGELIST imageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
ILC_MASK, 1, 1);
HICON ico = reinterpret_cast<HICON>(LoadImage(0,IDI_APPLICATION,
IMAGE_ICON,0,0,LR_SHARED));
ImageList_AddIcon(imageList, ico);
ListView_SetImageList(listView, imageList, LVSIL_SMALL);
The list view with three elements now has three application items.
However when I try to add another icon (IDI_HAND in this case), I still get the same 3 icons.
Another problem I have is that I can't fetch the actual file icons I need:
SHFILEINFO sfi;
SHGetFileInfo (L"C:\\test.txt", NULL, &sfi, sizeof (sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
ImageList_AddIcon(imageList, sfi.hIcon);
This results in empty icons, not the txt icons I want.
I've been struggling with this for ever, and I greatly appreciate your help here.
UPDATE
I'm using sample code I found on the Internet to fill the list view (obviously that's not what I want):
UINT columnMask = LVCF_TEXT|LVCF_FMT|LVCF_SUBITEM|LVCF_WIDTH;
LVCOLUMN lc[] = {
{ columnMask, 0, 150, L"Text...",0, 0,0,0 },
{ columnMask, LVCFMT_CENTER, 70, L"Number",0, 1,0,0 },
{ columnMask, 0, 100, L"Whatever",0, 2,0,0 },
};
ListView_InsertColumn(listView, 0, &lc[0]);
ListView_InsertColumn(listView, 1, &lc[1]);
ListView_InsertColumn(listView, 2, &lc[2]);
UINT itemMask = LVIF_TEXT;
LVITEM li[] = {
{ itemMask, 0,0, 0,0, L"...for the first item!",0, 0,0,0,0,0,0 },
{ itemMask, 0,1, 0,0, L"1",0, 0,0,0,0,0,0 },
{ itemMask, 0,2, 0,0, L"14 bucks",0, 0,0,0,0,0,0 },
{ itemMask, 1,0, 0,0, L"...for the second item!",0, 0,0,0,0,0,0 },
{ itemMask, 1,1, 0,0, L"24",0, 0,0,0,0,0,0 },
{ itemMask, 1,2, 0,0, L"2 suns",0, 0,0,0,0,0,0 },
{ itemMask, 2,0, 0,0, L"...for the second item!",0, 0,0,0,0,0,0 },
{ itemMask, 2,1, 0,0, L"24",0, 0,0,0,0,0,0 },
{ itemMask, 2,2, 0,0, L"2 suns",0, 0,0,0,0,0,0 },
{ itemMask, 3,0, 0,0, L"...for the second item!",0, 0,0,0,0,0,0 },
{ itemMask, 3,1, 0,0, L"24",0, 0,0,0,0,0,0 },
{ itemMask, 3,2, 0,0, L"2 suns",0, 0,0,0,0,0,0 },
};
// setting an icon like this doesn't work
li[0].iImage = sfi.iIcon;
ListView_InsertItem(listView, &li[0]);
ListView_SetItem(listView, &li[1]);
ListView_SetItem(listView, &li[2]);
ListView_InsertItem(listView, &li[3]);
ListView_SetItem(listView, &li[4]);
ListView_SetItem(listView, &li[5]);
ListView_InsertItem(listView, &li[6]);
ListView_SetItem(listView, &li[7]);
ListView_SetItem(listView, &li[8]);

The iImage member of LVICON is the index of the icon in the imagelist you passed to ListView_SetImageList. You are passing the index of the icon in the system imagelist, but the imagelist you passed to ListView_SetImageList is your private imagelist. Either
Use ListView_SetImageList to associate the imagelist with your private imagelist, and set the iImage to the index in your private imagelist (the return value from ImageList_AddIcon)
Use ListView_SetImageList to associate the imagelist with the system imagelist, and set the iImage to the index in the system imagelist.

For your second problem, try passing just the .extension, in your case pass .txt as the first param, and these flags: SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES or SHGFI_SMALLICON or SHGFI_ICON and on return, sfi.hIcon should contain the handle of the txt file icon
Without SHGFI_ICON, SHGetFileInfo is just filling in sfi.iIcon which is the index of the icon in the system imagelist, by adding SHGFI_ICON, SHGetFileInfo will also fill in sfi.hIcon which is what you want.
How are you adding the listview items? Show the code where you fill in the LVITEM structure.

Related

Win32 - Button images appear in wrong order in toolbar

I am creating a simple Paint application using win32 api (in visual studio). I have created a toolbar and added a bitmap for 10 toolbar images (TBbuttons.bmp - size: 160x16 pixel - 4bpp indexed format) as below:
However the button images do not appear in the correct order as shown above and, moreover, some images have a black line above them (which is not what i intended):
Here is the code i use to create the toolbar as well as those buttons:
InitCommonControls();
//create initial buttons
TBBUTTON tbButtons[] =
{
{ STD_FILENEW, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{ STD_FILEOPEN, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{ STD_FILESAVE, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}
};
//Create toolbar window
HWND hToolBarWnd = CreateToolbarEx(hWndParent,
WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | TBSTYLE_TOOLTIPS,
ID_TOOLBAR, sizeof(tbButtons) / sizeof(TBBUTTON), HINST_COMMCTRL,
0, tbButtons, sizeof(tbButtons) / sizeof(TBBUTTON),
BUTTON_WIDTH, BUTTON_HEIGHT, IMAGE_WIDTH, IMAGE_HEIGHT,
sizeof(TBBUTTON));
//Add more buttons
TBBUTTON buttonsToAdd[] =
{
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0 },
{ STD_CUT, IDM_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ STD_COPY, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ STD_PASTE, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ STD_DELETE, IDM_DELETE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }
};
SendMessage(hToolBarWnd, TB_ADDBUTTONS, (WPARAM)sizeof(buttonsToAdd) / sizeof(TBBUTTON),
(LPARAM)(LPTBBUTTON)&buttonsToAdd);
//Create 10 more buttons to draw
TBBUTTON userButtons[] =
{
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0 },
{ 0, IDM_ELLIPSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 1, IDM_FILLED_ELLIPSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 2, IDM_RECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 3, IDM_FILLED_RECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 4, IDM_CIRCLE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 5, IDM_FILLED_CIRCLE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 6, IDM_SQUARE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 7, IDM_FILLED_SQUARE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 8, IDM_LINE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 9, IDM_TEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }
};
TBADDBITMAP tbBitmap = { hInst, IDB_BITMAP1 };
//Add bitmap to toolbar
int idx = SendMessage(hToolBarWnd, TB_ADDBITMAP, (WPARAM)sizeof(tbBitmap) / sizeof(TBADDBITMAP),
(LPARAM)(LPTBADDBITMAP)&tbBitmap);
for (int i = 1; i <= 10; i++) {
userButtons[i].iBitmap += idx;
}
//Add button to toolbar
SendMessage(hToolBarWnd, TB_ADDBUTTONS, (WPARAM)sizeof(userButtons) / sizeof(TBBUTTON),
(LPARAM)(LPTBBUTTON)&userButtons);
I am still new to win32 api and i have no idea what is the cause of this. The application still runs fine but the buttons images are completely wrong. How can i fix this? Is it because of my code or the bitmap i created that caused the issue?
EDIT: I added a new bitmap i found from the Internet (TBbitmap2.bmp) as a test and created anew another bitmap (TBbitmap3.bmp) similar to the first one. Of all 3 bitmaps, the first one produced the problem in the question and the other 2 bitmaps worked fine. Here is the link to all 3 bitmaps. The question remains why the first bitmap kept producing the problem but the other 2 worked? (they have the same properties just different size).
I tried to create a sample and used the bitmap.
It does have some weird behavior. After I built the project for the first time, it did produce the problem you said. But after I rebuilt, the problem disappeared:
I think the bitmap was not loaded correctly during the build process, maybe you can try to rebuild the project and run the program.

Toolbar / CreateToolbarEx problem C++ doesn't display all bitmaps

Renders only 4 images with sperator instead of the whole 9 total with 2 separators, no idea what causes it the code looks great.
Here is my code.
void CreateMacroToolBar(HWND hDlg)
{
// Load and register Toolbar control class
INITCOMMONCONTROLSEX iccx;
iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC = ICC_BAR_CLASSES;
if (!InitCommonControlsEx(&iccx))
return;
const DWORD buttonStyles = TBSTYLE_AUTOSIZE | TBSTYLE_BUTTON;
const DWORD TOOLBAR_STYLE = WS_CHILD | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE |
CCS_NOPARENTALIGN |
CCS_NORESIZE |
CCS_NODIVIDER;
// Declare and initialize local constants.
const int numButtons = 7;
const int numButtonsTotal = 9;
TBBUTTON tbButtons[numButtonsTotal] =
{
{ 0, IDM_BUTTON_MACRO_RECORD, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)(L"Record a macro" },
{ 1, IDM_BUTTON_MACRO_STOP, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Stop recording" },
{ 2, IDM_BUTTON_MACRO_PLAY, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Play macro" },
{ I_IMAGENONE, -1, 0, TBSTYLE_SEP, {0}, 0, -1}, //SEPERATOR
{ 3, IDM_BUTTON_MACRO_ERASE, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Erase the macro" },
{ 4, IDM_BUTTON_MACRO_LOAD, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Load a macro" },
{ 5, IDM_BUTTON_MACRO_SAVE, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Save a macro" },
{ I_IMAGENONE, -1, 0, TBSTYLE_SEP, {0}, 0, -1}, //SEPERATOR
{ 6, IDM_MACRO_ABOUTBOX, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"About macro options" }
};
RECT rect;
HWND hwndTB;
hwndTB = CreateToolbarEx (GetDlgItem(hDlg, IDC_STATIC_TOOLBAR_MACRO), //Apply toolbar to static text.
TOOLBAR_STYLE, //Toolbar style.
ID_MACRO_TOOLBAR, //Toolbar ID.
numButtons, //Button of buttons (bmp's) (without seperators)
hDLLModule, //Current application instance (where the bitmap is)
IDR_TOOLBAR_MACRO, //Bitmap ID.
tbButtons, //Buttons struct
numButtonsTotal, //Total buttons (with seperators)
16, 15, 16, 15, //Button sizes and Bitmap sizes.
sizeof(TBBUTTON) );
if (!hwndTB) {
printf("Loading Macros failed!\n");
return;
}
//SendMessage(hwndTB, TB_AUTOSIZE, 0, 0); //Auto size to show more toolbars TODO: [DOESN'T WORK]
SendMessage(hwndTB, TB_SETMAXTEXTROWS, 0, 0); //Removes the label from Toolbar and adds Tooltips.
}
my IDE setup
my toolbar bitmap spliced image looks good
Here is how the bitmap looks in bitmap file .bmp (not the white area isn't accounted for I just did a bad print screen)
Here is how the static text looks like where it gets rendered
Here is how the static text Properties looks like where the toolbar gets rendered
Finished product when loading looks like this, note it only loads up the first 4 icons + 1 separator total of 5
Instead of 9 as needed with separators, or 7 if it loads only the images
A toolbar's height is determined by the height of the buttons, and a toolbar's width is the same as the width of the parent window's client area, also by default. In this case you have passed GetDlgItem(hDlg, IDC_STATIC_TOOLBAR_MACRO) this is likely the static label. Which would limit the width of the toolbar to the width of that static control. I believe if you pass hDlg as the first parameter to CreateToolbarEx it will resolve your issue. Or create a new window to contain it that's large enough, who's parent is hDlg.
Removing these 2 styles from all buttons fixes the problem.
CCS_NOPARENTALIGN | CCS_NORESIZE

Directx 9 - is the SetScissorRect behavior same for surfaces?

First off, i need to use directx 9 for compatibility,
i started drawing a text with
RECT pos { 2, 2, 100, 100 };
if(!gfont)
D3DXCreateFont( iDev, 20, NULL, NULL, NULL, NULL, DEFAULT_CHARSET, NULL, ANTIALIASED_QUALITY, NULL, "Segoe UI Light", &gfont );
else
{
gfont->DrawText( NULL, "Sample", -1, &pos, NULL, D3DCOLOR_ARGB( 255, 0, 255, 255 ) );
}
and it's all right, i get:
so if we add SetScissorRect
RECT protectedRect { 2, 2, 50, 50 };
iDev->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
iDev->SetScissorRect( &protectedRect );
i get:
which it's the right result, now if i do with surfaces, the surface it's loaded with D3DXLoadSurfaceFromFile() and allocated with CreateOffscreenPlainSurface() from a jpg file...
iDev->GetBackBuffer(NULL, NULL, D3DBACKBUFFER_TYPE_MONO, &backBuffsfc);
iDev->UpdateSurface(sfc, NULL, backBuffsfc, NULL);
RECT protectedRect { 2, 2, 50, 50 };
iDev->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
iDev->SetScissorRect( &protectedRect );
the surface keeps appearing completely like
the question is, why is not clipped like the text?

I can't set my custom ICO icons on toolbar buttons in Win32 application

I apologize for my poor English. I write a C ++ application in the Win32 API in Visual Studio 2017 Community on Windows 10. The application has a toolbar with buttons. I want to assign my custom functionality to each button. Therefore, each button must have its custom specific icon. (I added the icons to the application’s ResourceFiles folder.) The problem is that I can’t install my custom ICO icons on the buttons in the toolbar. When I run my application, the buttons are empty without icons. I re-read a lot of information on this topic on SO and on other sites. Still, I can’t install my icons on the buttons. I would be very grateful if anyone would help. Thank you in advance. Below is my code, with which I try to put my icons on the toolbar buttons:
#define IDM_INPUT 0
#define IDM_OUTPUT 1
#define IDM_TRIANGULATE 2
#define IDM_STOP 3
HWND CreateSimpleToolbar(HWND hWndParent)
{
// Declare and initialize the constants used in the function:
// - picture list id for buttons,
const int ImageListID = 0;
// - number of buttons,
const int numButtons = 4;
// - the size of each image for the button.
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, hInst, NULL);
if (hWndToolbar == NULL)
return NULL;
// Create a list of pictures for buttons.
g_hImageList = ImageList_Create(bitmapSize, bitmapSize,
ILC_COLOR16 | ILC_MASK, // Provide a transparent background.
numButtons, 0);
ImageList_AddIcon(g_hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1)));
ImageList_AddIcon(g_hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON2)));
ImageList_AddIcon(g_hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON3)));
ImageList_AddIcon(g_hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON4)));
// Set a list of pictures for buttons.
SendMessage(hWndToolbar, TB_SETIMAGELIST,
(WPARAM)ImageListID,
(LPARAM)g_hImageList);
// Upload pictures for buttons.
SendMessage(hWndToolbar, TB_LOADIMAGES,
(WPARAM)IDB_STD_SMALL_COLOR,
(LPARAM)HINST_COMMCTRL);
// Initialize information about buttons.
TBBUTTON tbButtons[numButtons] =
{
{ MAKELONG(IDI_ICON1, ImageListID), IDM_INPUT, TBSTATE_ENABLED, buttonStyles, {0}, 0, 0 },
{ MAKELONG(IDI_ICON2, ImageListID), IDM_OUTPUT, TBSTATE_ENABLED, buttonStyles, {0}, 0, 0},
{ MAKELONG(IDI_ICON3, ImageListID), IDM_TRIANGULATE, TBSTATE_ENABLED, buttonStyles, {0}, 0, 0},
{ MAKELONG(IDI_ICON4, ImageListID), IDM_STOP, TBSTATE_ENABLED, buttonStyles, {0}, 0, 0}
};
// 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;
}
IDI_ICON1, IDI_ICON2, IDI_ICON3 and IDI_ICON4 are the identifiers of the four ICO icon files resulting from the addition of these icons to the application resources.
If I check the result of the LoadIcon function in the debugger, I will see the message "Unable to read memories", although the returned HICON value itself is not zero.
Please tell me what needs to be fixed in the above code?

How to clear drawing area for ActiveX OCX control?

I have some trouble drawing an ActiveX control. In the screenshot below you see the control after a resize in the VB6 IDE. The control's outline from before the resize is still shown on the left-hand side of the control:
Here is the code that draws a black ellipsis with a red Z:
void CzFileIoXCtrl::OnDraw(CDC* pdc,
const CRect& rcBounds,
const CRect& rcInvalid)
{
if (!pdc)
{
return;
}
pdc->SetBkMode(TRANSPARENT);
pdc->SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));
pdc->Ellipse(rcBounds.left, rcBounds.top,
rcBounds.left + rcBounds.Width(),
rcBounds.top + rcBounds.Height());
HFONT font = CreateFont(int(rcBounds.Height() * 0.7),
int(rcBounds.Width() * 0.5),
0, 0, FW_BLACK, FALSE, FALSE, FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
FF_DECORATIVE, NULL);
pdc->SelectObject(font);
pdc->SetTextColor(RGB(255, 0, 0));
DRAWTEXTPARAMS params = { sizeof(DRAWTEXTPARAMS), 1, 0, 0, 1 };
RECT bounds = rcBounds;
CString z(L"Z");
pdc->DrawTextEx(z, &bounds, DT_CENTER | DT_VCENTER | DT_SINGLELINE, &params);
}
How can I clear the drawing area?
I managed to reproduce this in the vb form editor. It looks like the problem comes because you do not draw anything outside the ellipse. So, you can draw a rectangle in the entire area like this before drawing anything in OnDraw().
pdc->FillRect( rcBounds, &CBrush(TranslateColor( AmbientBackColor() )) );
I tested this and is working fine.