GDI : Get LOGPEN from HGDIOBJ or HPEN - mfc

I would like to get LOGPEN structure for currently using HGDIOBJ(which is actually HPEN). Lets assume we have something like this:
CPen ColoredPen;
ColoredPen.Create(...);
...
HGDIOBJ PriorPen = SelectObject(PaintingDC, ColoredPen);
Now I need to get LOGPEN structure from PriorPen. I tried in 2 ways:
1. LOGPEN LogPen;
CPen* pPen = CPen::FromHandle((HPEN)PriorPen);
pPen->GetLogPen(&LogPen);
2. LOGPEN LogPen;
GetObject(PriorPen, sizeof(LogPen), &LogPen);
None of these give me a correct LOGPEN structure object because all fields are 0. I also tried to get LOGPEN for actual CPen and it works perfectly:
ColoredPen.GetLogPen(&LogPen);
but I need to work only with HPEN. So my question is how can I get LOGPEN from HPEN?

You can do the following:
LOGPEN LogPen;
CPen* pTempPen = CPen::FromHandle(hPen);
pTempPen->GetLogPen(&LogPen);
Please note that this temporary CPen object is valid only until the next time the application has idle time in its event loop, at which time all temporary graphic objects are deleted. In other words, the temporary object is only valid during the processing of one window message.

Related

How to insert hyperlink without underline to Win32 RichEdit?

I added a link to RichEdit, use CFM_LINK/CHARFORMAT2 structure. But I can't figure out how to remove the underline effect. I tried:
SendMessage(richEditHWND, EM_AUTOURLDETECT, FALSE, NULL);
SendMessage(richEditHWND, EM_SETEDITSTYLEEX, 0, SES_EX_HANDLEFRIENDLYURL);
CHARFORMAT2 cf2;
memset(&cf2, 0, sizeof(CHARFORMAT2));
cf2.dwMask = CFM_LINK| CFM_UNDERLINE | CFM_COLOR | CFM_LINKPROTECTED;
cf2.dwEffects = CFE_LINK| CFE_UNDERLINE | CFE_LINKPROTECTED;
cf2.crTextColor = RGB(255, 0, 0);
cf2.bUnderlineType = CFU_UNDERLINENONE;
SendMessage(richEditHWND, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
But it don'n work.
Another way is set underline color to white color, which is the RichEdit background color, but it is a hacky way, make character like q, j,... being cut apart, also show the line when select text.
So what's the correct way to do this?
Note: I'm using RICHEDIT50W class.
You can do this using a friendly-name hyperlink. These let you specify arbitrary text (along with its own color and formatting) that is used for display, and the actual URL is hidden.
By default, friendly-name hyperlink text is also displayed in blue
with a blue underline unless the name text is formatted with an
explicit color. Explicit formatting takes precedence
The displayed text needs to have the CFE_LINK and CFE_LINKPROTECTED styles, along with explicit color and formatting styles. You then set the URL using the ITextRange2::SetURL method.
The MSDN blog post RichEdit Friendly Name Hyperlinks has a more detailed description of how to use them.
I just encountered the same problem recently and I just found that it's a bug of Richedit library. When I updated it from v4.1 to v5.0 the underline could be removed with no issues
Try sending an EM_AUTOURLDETECT message to the RichEdit control with wParam=0, lParam=0
"Specify 0 to disable automatic link detection...": https://msdn.microsoft.com/en-us/library/windows/desktop/bb787991(v=vs.85).aspx

WIN32API: owner-drawn button creates white background around the text when clicked

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);

How do I draw a fine line like TreeView

I would like to be able to draw a file line using native Windows API (LineTo) like the one that TreeView uses to connect nodes to each other. But using RS_DOT to create the brush (::CreatePen(PS_DOT, 0, RGB(200, 200, 200))), produces a different kind of line. Does anyone know how I can draw such a line?
Creating a true dotted pen
LOGBRUSH LogBrush;
LogBrush.lbColor = c_colorGridLine;
LogBrush.lbStyle = PS_SOLID;
penDotted.CreatePen( PS_COSMETIC | PS_ALTERNATE , 1, &LogBrush, 0, NULL );

Tool tips for custom made control using CToolTipCtrl ? (MFC)

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);

Convert HICON to the unsigned long

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.