How to get a folder's open icon with SHGetFileInfo() method? - c++

This is what I did:
LPMALLOC malloc;
LPITEMIDLIST pidl;
SHFILEINFO FileInfo;
SFGAOF sfGao;
if (SUCCEEDED(SHGetMalloc(&malloc))
{
if (SUCCEEDED(SHParseDisplayName(strDirPath, NULL, &pidl, SFGAO_FOLDER, &sfGao)))
{
SHGetFileInfo((LPCWSTR)(PCHAR(pidl)), 0, &FileInfo, sizeof(FileInfo), SHGFI_PIDL | SHGFI_ICON);
CDC* pDC = GetWindowDC();
pDC->DrawIcon(10, 10, FileInfo.hIcon);
ReleaseDC(pDC);
}
malloc->Free(pidl);
}
malloc->Release();
Here's the problem: I found that I can get the icon of a folder easily with this approach. But I could not get its open icon, when I set the fourth parameter of SHGetFileInfo method to be SHGFI_PIDL | SHGFI_OPENICON. The hIcon of FileInfo is always NULL, and I don't know why.
Can anyone tell me how to fix the problem?

From the comments:
I have resolved the problem. Modify the fourth parameter from SHGFI_PIDL | SHGFI_OPENICON to SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_OPENICON, then I was able to retrieve the open icon of the specified folder.

Related

How should I change the IMAGE(doesn't matter the type) of the button in the toolbar in MFC applications?

I know that this is stupid problem but I am stuck with it for the past 4 days. Why it is so complicated to just modify the toolbar in the MFC apps?
I create New Visual studio MFC application that is dialog based. I create new Toolbar resource. And then how should I set images(png, bitmap, jpeg...) or whatever type to be used in my toolbar?
I have set size to w50 and h50 and I can draw inside the buttons. But I cant find way to use image.
Instead this 2 buttons that I have just tried if its working, I want to use 8 images that are in bitmap format and in png. I read somewhere that PNG is not supported by MFC applications so I converted to Bitmap.
I load my toolbar in the dialog app like this in the OnInitDialog() method:
DWORD dwCtrlStyle = TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CBRS_SIZE_DYNAMIC;
DWORD dwStyle = AFX_DEFAULT_TOOLBAR_STYLE;
CMFCToolBar::m_dblLargeImageRatio = 1;
if (m_ToolBar.CreateEx(this, dwCtrlStyle, dwStyle, CRect(1, 1, 1, 1), IDR_TOOLBAR1))
{
dwStyle = CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC;
m_ToolBar.SetPaneStyle(m_ToolBar.GetPaneStyle() | dwStyle);
CMFCToolBarInfo info;
m_ToolBar.LoadToolBarEx(IDR_TOOLBAR1, info, FALSE);
CSize sizeToolBar = m_ToolBar.CalcFixedLayout(TRUE, TRUE);
m_ToolBar.SetWindowPos(NULL, 0, 0, sizeToolBar.cx, sizeToolBar.cy, SWP_NOACTIVATE |
SWP_NOZORDER);
CPoint ptOffset(0, sizeToolBar.cy);
}
Please if someone can help me I would be really grateful. The image format doesn't matter. I just want to put image in the toolbar.
This is my app currently:
UPDATE: I have tried this way. ID_BUTTON_1 if the first button in the toolbar and i tried to change its image. But with this there is no button in the toolbar at the place for the first button. What I am doing Wrong?
VERIFY(m_toolbar.LoadBitmap(IDB_BITMAP1));
CMFCToolBarButton mbutton;
mbutton.SetImage(m_toolbar.GetImages()->GetCount() - 1);
m_toolbar.ReplaceButton(ID_BUTTON_1, CMFCToolBarButton(ID_BUTTON_1, 0));
I answered this recently and can no longer find my answer. You can use PNG images for your toolbars. Under the hood you still use the BMP version for the resource editor to create your event handlers etc. But you can then add your PNG as a resource and then load it into your dialog.
For example, I call this in my OnInitDialog function:
void CMeetingScheduleAssistantDlg::CreateToolbar()
{
DWORD dwCtrlStyle = TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CBRS_SIZE_DYNAMIC;
DWORD dwStyle = AFX_DEFAULT_TOOLBAR_STYLE;
CMFCToolBar::m_dblLargeImageRatio = 1; // AJT v20.1.7 Bug fix
if (m_ToolBar.CreateEx(this, dwCtrlStyle,
dwStyle, CRect(1, 1, 1, 1), IDR_TOOLBAR))
{
dwStyle = CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC;
m_ToolBar.SetPaneStyle(m_ToolBar.GetPaneStyle() | dwStyle);
CMFCToolBarInfo info;
info.m_uiColdResID = IDB_PNG_MAIN_TOOLBAR;
info.m_uiHotResID = IDB_PNG_MAIN_TOOLBAR;
info.m_uiLargeColdResID = IDB_PNG_MAIN_TOOLBAR;
info.m_uiLargeHotResID = IDB_PNG_MAIN_TOOLBAR;
m_ToolBar.LoadToolBarEx(IDR_TOOLBAR, info, FALSE);
CSize sizeToolBar = m_ToolBar.CalcFixedLayout(TRUE, TRUE);
m_ToolBar.SetWindowPos(NULL, 0, 0, sizeToolBar.cx, sizeToolBar.cy,
SWP_NOACTIVATE | SWP_NOZORDER);
// Move all controls down
CPoint ptOffset(0, sizeToolBar.cy);
CRect rcChild;
CWnd* pwndChild = GetWindow(GW_CHILD);
while (pwndChild)
{
if (pwndChild->GetSafeHwnd() != m_ToolBar.GetSafeHwnd())
{
pwndChild->GetWindowRect(rcChild);
ScreenToClient(rcChild);
rcChild.OffsetRect(ptOffset);
pwndChild->MoveWindow(rcChild, FALSE);
}
pwndChild = pwndChild->GetNextWindow();
}
// Resize the window
CRect rcWindow;
GetWindowRect(rcWindow);
rcWindow.bottom += sizeToolBar.cy;
MoveWindow(rcWindow, FALSE);
}
}
I don't know where my previous answer has gone to, else I would have flagged this as duplicate. #confused.

I cannot load image from folder using win32

I am new to win32. I placed the bitmap image 'logo2.bmp' into the directory which .vcxproj is there. However, when I used the LoadImage() function, it seems that nothing is loaded.
I have checked my questions online, but the image still cannot be loaded after the modification.
void AddControls(HWND hwnd)
{
//some code
hLogo = CreateWindowW(L"Static", NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP,
350, 60, 100, 100, hwnd, NULL, NULL, NULL);
if (hLogoImage != NULL)
{
SendMessage(hLogo, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hLogoImage);
}
else
{
MessageBox(0, L"Could not load image", L"Error", MB_OK);
}
}
void loadImages()
{
hLogoImage = (HBITMAP)LoadImage(NULL, L"logo2.bmp", IMAGE_BITMAP,
0,0,LR_LOADFROMFILE | LR_DEFAULTSIZE);
}
I expect the output is a bitmap image successfully displayed on the windows, but the 'Error' text box was displayed and no picture displayed instead.
Edit: Okay, I understand that this is a problem of file format. I better study more.

Is it possible to change font for an edit control without affecting the other lines?

Hello I want to know if it is possible to change the font of an edit control for some lines only without affecting the remaining:
In my Edit control I have a text but I want some headlines and titles in bigger font and bold while the other lines are with smaller font.
I tried SendMessage(hEdit, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(0, true));
But it sets the whole text in the passed in font.
I thought some messing up with SelectObject(hDcEdit, hFont); But I don't know if it is correct and how.
A standard Edit Control (think, Notepad) does not support what you are looking for. It only supports one Font for the entire text.
What you are looking for is a RichEdit Control instead (think, Wordpad), and in particular its EM_SETCHARFORMAT message, which can be used to apply different formatting (including fonts, colors, etc) to different sections of text.
This is not working with the default Editcontrol, but you can use a Richeditcontrol
#include <Windows.h>
#include <CommCtrl.h>
HINSTANCE relib = LoadLibrary("riched32.dll");
if (relib == NULL) {
MessageBox(NULL, "couldn't load richedit32.dll", "", MB_ICONEXCLAMATION);
hEdit = CreateWindow(RICHEDIT_CLASS, "", WS_VISIBLE | WS_CHILD | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL, 0, 0, 200, 200, hWnd, NULL,
NULL, NULL);
Now to set the font to your Richeditcontrol use:
CHARFORMAT2 cf;
memset(&cf, 0, sizeof cf);
cf.cbSize = sizeof cf;
cf.dwMask = CFM_FACE;
wsprintf(cf.szFaceName, "Arial"); //Here you can set the fontname you wont (C:/Windows/Fonts)
SendMessage(hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);

Selecting and Highlighting an Item from List View

I would like to select and highlight an item from a list view control and am using the following code
#include <Windows.h>
#include <commctrl.h>
int main() {
//Hardcoded Handle to the ListView Windows of Add Printer Dialog
HWND hwndListView = (HWND)0x000206D6;
DWORD dwProcessID;
::GetWindowThreadProcessId( hwndListView, &dwProcessID );
HANDLE process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
LVITEM lvi;
LVITEM* _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
lvi.state = LVIS_FOCUSED | LVIS_SELECTED ;
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED ;
lvi.mask = LVIF_STATE;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hwndListView, LVM_SETITEMSTATE, (WPARAM)0, (LPARAM)_lvi);
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
}
The result I am getting is
instead of the item getting selected and highlighted
Please let me know what might be going wrong
There are restrictions on which processes can set focus on a window, and chances are that the app selecting the ListView items does not satisfy those restrictions while the dialog is active. For example, the HWND being focused must be attached to the calling thread's message queue. So the highlighting app will have to use AttachThreadInput() before calling SetFocus() on another app's windows.

How to get file icon using C++

I want to add Icon to treeview node, using C++. I want to get the icons from system, I tried
I tried with,
PMString ucPath("C:\\path\\to\\file.extension");
SHFILEINFO info;
::SHGetFileInfo(ucPath.GrabTString(), FILE_ATTRIBUTE_NORMAL, &info, sizeof(info),
SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON);
iconView->SetRsrcID((RsrcID) info.hIcon);
::DestroyIcon(info.hIcon);
where, SetResrcID ,PMString are the InDesing API and iconView is the controlView of the Tree, I am not getting what's going wrong, if anyone has idea please suggest.
Thanks,
Praveen Mamdge
Here is the codes what I'm using in my application, you should change the icon to a bitmap.
PMString ucPath("C:\\path\\to\\file.extension");
SHFILEINFO info;
::SHGetFileInfo(ucPath.GrabTString(), FILE_ATTRIBUTE_NORMAL, &info, sizeof(info),
SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON);
ICONINFO stIconInfo;
GetIconInfo(s_sfi.hIcon, &stIconInfo);
HBITMAP hBmp = stIconInfo.hbmColor;
DestroyIcon(s_sfi.hIcon) ;
The best way to do it is using the system icon index with SHGFI_SYSICONINDEX.
Some thing like this,
Extract icon from file first.
SHFILEINFO stFileInfo;
SHGetFileInfo( file,
FILE_ATTRIBUTE_NORMAL,
&stFileInfo,
sizeof( stFileInfo ),
SHGFI_ICON | SHGFI_LARGEICON );
Then add to imagelist and use the index to set icon.
m_nIndex = m_ilLargeIcons.Add( stFileInfo.hIcon );
This is your code snippet, observe line by line:
PMString ucPath("C:\path\to\file.extension"); SHFILEINFO info;
::SHGetFileInfo(ucPath.GrabTString(), FILE_ATTRIBUTE_NORMAL, &info, sizeof(info),
SHGFI_ICON |
SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON);
iconView->SetRsrcID((RsrcID) info.hIcon);
::DestroyIcon(info.hIcon);
After this line: iconView->SetRsrcID((RsrcID) info.hIcon);, you called ::DestroyIcon that destroyed that icon you stored.