I am trying to get the Icon from the system. by using SHGetFileInfo I got the HICON,
I tested this HICON with the following code:
SHFILEINFO info; //For getting information about the file
if (::SHGetFileInfo(ucPath.GrabTString(), 0,&info, sizeof(info), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SHELLICONSIZE) != NULL)
{
//Control view of the
if (iconView != NULL){
HDC hDC = GetDC(NULL); //Get the screen DC
DrawIconEx(hDC, 300, 200, info.hIcon, 0, 0, 0, NULL, DI_NORMAL); //Draw icon on 300, 200 location
ReleaseDC(NULL, hDC);
//following line is not working
iconView->SetRsrcID((unsigned long) info.hIcon);
}
::DestroyIcon(info.hIcon);
}
on the screen at location (300, 200) it shows me icon,
I want to set this icon to the tree view, for that I require the resource id,
Please suggest if any one knows, How to convert this Handle to unsigned long.
Thanks,
Praveen Mamdge
A resource id is an identifier to a resource you have within your executable. You use this identifier with MAKEINTRESOURCE for functions requiring resource identifiers.
As for tree view, you use the TreeView_SetImageList, and then each items gets an index relative to this list.
You therefore need to build an image list with the icons you want to use, pass it to the tree view and then use the appropriate index for each item.
To create an manipulate an imagelist, you can use ImageList_Create & ImageList_AddIcon, etc.
It's sooo 1990. :)
A HANDLE is not a resource ID. Most functions that can take a file and resource ID also have a version that takes the HANDLE directly.
This link on CodeProject might be what you're looking for.
Related
I created a button and I want to display an image on it. After some research I found the following code:
HBITMAP buttonImage;
buttonImage = (HBITMAP)LoadImageW(NULL,L"Button.bmp",IMAGE_BITMAP,95,35,LR_LOADFROMFILE);
HWND playBTN = CreateWindow(TEXT("button"),NULL,WS_VISIBLE | WS_CHILD | BS_BITMAP,330, 400, 95, 35, hwnd, (HMENU)1, NULL, NULL);
SendMessageW(playBTN,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM) buttonImage);
The code runs succesfuly but there isnt any change at the button
I also tried using LR_DEFAULTCOLOR,LR_VGACOLORand LR_LOADMAP3DCOLORS but nothing changed.
Note: The image I want to display is a box with green color
I have an MFC program written that reads files, stores the data, and draws it as text on the client view.
I want to make a menu button View->Split that splits the client area into two, separately scrolling views displaying the same data.
I saw some things about CWndSplitter online and read through some documentation but none of it has proved to be useful because they talk about using OnCreate and deleting the default view to get it to work. This is not an option. I want to keep the default view, but split it in two if the user clicks the button.
I've currently created a CWndSplitter member variable and defined a menu button event handler in my SDI-1View.cpp. When called, it does absolutely nothing but cause the screen to flicker and a second click crashes the program.
void CSDI1View::OnViewSplit32778()
{
// TODO: Add your command handler code here
/*
int rows = 2;
int columns = 1;
if (!m_wndSplitter.CreateStatic(this, rows, columns))
return;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL) ||
(!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL)))
{
m_wndSplitter.DestroyWindow();
return;
}
*/
}
Can anyone tell me what the normal approach to splitting a client view in half is? I just want to integrate that into an event handler.
Any help would be greatly appreciated.
Thanks.
--------------------------------EDIT----------------------------------
I now have the following code in my Split button event handler, thanks to the outline provided by xMRi, but it is still not working properly...
void CMainFrame::OnViewSplit()
{
// TODO: Add your command handler code here
//calculate client size
CRect cr;
GetClientRect(&cr);
if (!m_mainSplitter.CreateStatic(this, 2, 1))
{
MessageBox(_T("Error setting up splitter frames! (CreateStatic)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
// Set the parent of the splitter window to the current view
CSDI1View * view = CSDI1View::GetView();
m_mainSplitter.SetParent(this);
view->SetParent(&m_mainSplitter);
// Create a CCreateContext
CCreateContext cc;
CRuntimeClass* prt = RUNTIME_CLASS(CSDI1View);
cc.m_pNewViewClass = prt;
cc.m_pCurrentDoc = view->GetDocument();
cc.m_pNewDocTemplate = NULL;
cc.m_pLastView = NULL;
cc.m_pCurrentFrame = this;
if (!m_mainSplitter.CreateView(0, 0,
cc.m_pNewViewClass,
CSize(cr.Width(), cr.Height()/2), &cc))
{
MessageBox(_T("Error setting up splitter frames! (CreateView 1)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
if (!m_mainSplitter.CreateView(1, 0,
cc.m_pNewViewClass,
CSize(cr.Width(), cr.Height()/2), &cc))
{
MessageBox(_T("Error setting up splitter frames! (CreateView 2)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
m_bInitSplitter = TRUE;
}
Upon clicking the view->split button, I get a "Debug Assertion Error" popup and the first call to CreateView returns FALSE, displaying my messagebox: "Error setting up splitter frames! (CreateView 1)"
A static splitter is for a static split--i.e., a window that's always split. You usually use it when you want to have a different view in each pane of the split (e.g. display a column of numbers in one pane, and a graph in the other pane).
For a situation like yours that you want to be able to have the window, then later split it and have two essentially identical views, you (at least normally) want to use a dynamic splitter.
At least normally, you create the splitter when you create the view. That will create a window that has a handle at the top, right-hand corner that the user pulls down to split the view:
To split the window, the user pulls down on the handle:
When the split is where they want it, they release the mouse button, and the view splits into two separately scrollable sections:
Since you didn't specify whether you wanted vertical or horizontal splitting, I set this one up to allow either or both:
The code for this looks something like this:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
return my_splitter.Create(this,
2, 2, // 2 rows, 2 columns
CSize(20, 20), // minimum pane size
pContext);
}
where my_splitter is defined something like this:
CSplitterWnd my_splitter;
If you want to use a splitter window on demand, you need to change the parent of the current view.
So the steps are:
create a simple SDI application
On demand create a splitter window
Use SetParent to the current view and set it as a parent in the splitter window.
Create another window in the second splitter.
And the way back.
Use SetParent and attach the normal view back to the main frame.
Destroy the splitter
There are active samples how to switch a view in a current document (MSDN). It helps you how IDs must be replaced and changed.
I have created an Owner-Drawn button . I use the WM_CTLCOLORBTN message in order to paint it :
//get the text of the button
wchar_t buttonText[20];
int textLength = SendMessage((HWND)lParam,WM_GETTEXT,20,(LPARAM)buttonText);
Font FootlightMTLight(L"Footlight MT Light",20,0,false,false,false,L"Black");
SelectObject((HDC)wParam,FootlightMTLight.getWindowHandle());
TextOut((HDC)wParam,30,15,buttonText,textLength);
SetTextColor((HDC)wParam, RGB(0,0,0));
SetBkColor((HDC)wParam, RGB(229,255,229));
PatBlt((HDC)wParam,0,0,1,50,BLACKNESS); //x,y,width,height
PatBlt((HDC)wParam,269/2-1,0,1,50,BLACKNESS);
PatBlt((HDC)wParam,0,49,269/2,1,BLACKNESS);
PatBlt((HDC)wParam,0,0,269/2,1,BLACKNESS);
static HBRUSH handleToButtonBrush = CreateSolidBrush(RGB(229,255,229));
return (INT_PTR)handleToButtonBrush;
"Font" is an object I created (I wrapped HFONT handle and CreateFont function with class etc. getWindowHandle() basically returns HFONT ).
the button renders nicely , yet pressing on it make the text-background turn white.
I search the net for a reason and a solution yet I didn't find a concrete one.
thanks in advanced!
You need to call those lines before the actual text drawing occurs
SetTextColor((HDC)wParam, RGB(0,0,0));
SetBkColor((HDC)wParam, RGB(229,255,229));
TextOut((HDC)wParam,30,15,buttonText,textLength);
I made a custom control derived from CWnd (a line chart) and I'm wondering if I can use CToolTipCtrl for displaying tool tips for points on the graph. If yes, how could I do that?
Btw, when I move my mouse over the point, the rectangle containg string with information about values of the point, should pop up.
Yes, this works, actually I do this exact same thing, also in a line graph chart, however there are a few drawbacks/remarks. The message handling is a bit wonky, with some messages not being send according to the documentation, and some workarounds being necessary to keep the control self-contained (not requiring help from the parent to reflect notifications).
What you do is declare a variable in your CWnd-derived class
CToolTipCtrl m_ToolTipCtrl;
CString m_ToolTipContent;
Then do this on OnCreate:
m_ToolTipCtrl.Create(this, TTS_ALWAYSTIP);
m_ToolTipCtrl.Activate(TRUE);
Optionally, you can also set the delay time:
m_ToolTipCtrl.SetDelayTime(TTDT_AUTOPOP, -1);
m_ToolTipCtrl.SetDelayTime(TTDT_INITIAL, 0);
m_ToolTipCtrl.SetDelayTime(TTDT_RESHOW, 0);
When you want to show your tooltip (presumably in OnMouseMove()), use
m_ToolTipCtrl.Pop();
BUT this only works in UNICODE builds. So if you're still on MBCS (like I am), you can only show the tooltip after a certain delay.
Use this to set your tooltip text (also in OnMouseMove):
// Not using CToolTipCtrl::AddTool() because
// it redirects the messages to the parent
TOOLINFO ti = {0};
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND; // Indicate that uId is handle to a control
ti.uId = (UINT_PTR)m_hWnd; // Handle to the control
ti.hwnd = m_hWnd; // Handle to window
// to receive the tooltip-messages
ti.hinst = ::AfxGetInstanceHandle();
ti.lpszText = LPSTR_TEXTCALLBACK;
ti.rect = <rectangle where, when the mouse is over it, the tooltip should be shown>;
m_ToolTipCtrl.SendMessage(TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
m_ToolTipCtrl.Activate(TRUE);
m_ToolTipContent = "my tooltip content";
Furthermore, you need to handle TTNNeedText:
// The build-agnostic one doesn't work for some reason.
ON_NOTIFY_EX(TTN_NEEDTEXTA, 0, OnTTNNeedText)
ON_NOTIFY_EX(TTN_NEEDTEXTW, 0, OnTTNNeedText)
BOOL GraphCtrlOnTTNNeedText(UINT id, NMHDR* pTTTStruct, LRESULT* pResult)
{
TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*)pTTTStruct;
//pTTT->lpszText = "some test text";
//pTTT->lpszText = m_ToolTipContent;
strncpy_s(pTTT->lpszText, 80, m_ToolTipContent, _TRUNCATE);
return TRUE;
}
You'll have to modify this a bit, and read the documentation of the functions and messages, to get this to work in your project but yes it can be done.
For those that may still be looking for an answer to this as I was. (I couldn't get the one above to work - Things in MFC may have changed.)
All code is contained within the custom control class.
In your class definition add:
CToolTipCtrl ToolTip;
In PreSubclassWindow() add:
#define TOOLTIP_ID 1
ToolTip.Create(this, TTS_ALWAYSTIP );
CRect rc;
GetClientRect(rc);
ToolTip.AddTool(this, "Tool tip text", rc, TOOLTIP_ID);
In PreTranslateMessage() add:
ToolTip.RelayEvent(msg);
Whenever your tool tip text changes add:
ToolTip.UpdateTipText("New Tip Text", this, TOOLTIP_ID);
I know how to draw a button in C++ but how would i make an icon on it can someone post source or give reference please? by SendMessage() or if not that way just please paste
Please need easier anwsers without so many files im new a bit
Since you're new, you may also wish to consult the MSDN Library. You can find information on Button Styles (see, specifically, the BS ICON and BS BITMAP styles) and the BM_SETIMAGE message .
If you use MFC then I would recommend you to use the following CButton method SetIcon:
CButton myButton;
// Create an icon button.
myButton.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_ICON,
CRect(10,10,60,50), pParentWnd, 1);
// Set the icon of the button to be the system question mark icon.
myButton.SetIcon( ::LoadIcon(NULL, IDI_QUESTION) );
This works very well.
send BM_SETIMAGE message, and pass loaded image handle to lParam.
button1 = CreateWindowW(L"BUTTON", L"&Button", WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_BITMAP, 20, 50, 80, 25, hwnd, (HMENU) 600, NULL, NULL);
hImg = LoadImageW(NULL, L"test123.bmp", IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);
SendMessageW(button1, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImg);
P.S: you need to use BS_BITMAP flag when CreateWindow()