Displaying a tooltip with an icon - winapi

I want to display a tooltip with text and an icon when the mouse pointer hovers over a specific button. Below are two variants of this that I've seen, but I couldn't find information about the implementation.
(source: microsoft.com)

Take a look at TTM_SETTITLE message -- custom Icons can be used in Windows XP SP2 and later.

#Edward Clements already told you an useful way, so you maybe know how to use it.
Anyway, I just add detailed code for refernce.
case WM_CREATE:
hTip=CreateWindowEx(WS_EX_TOPMOST,TOOLTIPS_CLASS,NULL,0,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
hWnd,NULL,g_hInst,NULL);
hBtn=CreateWindow("button","Test",WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
50,50,200,100,hWnd,(HMENU)0,g_hInst,NULL);
ti.cbSize=sizeof(TOOLINFO);
ti.uFlags=TTF_SUBCLASS | TTF_IDISHWND;
ti.hwnd=hWnd;
ti.uId=(WPARAM)hBtn;
ti.lpszText="This is a button";
SendMessage(hTip,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
SendMessage(hTip, TTM_SETTITLE, (WPARAM)TTI_WARNING, (LPARAM)"Information");
return 0;

Related

WIN32: Duplicate Standard Button Control (disabled Icon / hotkey underline) in Owner Draw Button?

So for the simple feat of wanting to put an icon on the right side of button text instead of the left resulted in having to use owner draw buttons (but someone here said Custom Draw is actually available if using visual themes). Okay, fine, but now I'm finding you can't really duplicate what Windows standard buttons do when it's not in owner draw mode.
For a normal enabled button I can get the look correct by checking if visual styles are available or not and then using either the DrawThemeBackground() / DrawThemeText() or DrawFrameControl() / DrawText(). However the hot key underline character is shown even when alt key is not pressed, the default buttons don't show it until alt pressed.
For a disabled button, I can't duplicate the disabled look of the icon placed on the button. I tried DrawState() over DrawIconEx() but that looks like the old Windows 3.1 type grey graphic not the visual style dimmed graphic. I see there is a DrawThemeIcon() for an image list, I guess I could try that (I'd have to test non visual style mode to see if DrawState() matches when not using visual styles).
Also, as you hover over the button, the state doesn't change, I understand that if using owner draw, that doesn't occur, maybe it would still work with Custom Draw?
So the two main questions are:
1 - Is there something built-in to the button / owner draw to handle the underlined hotkey only when alt was pressed?
Update to Question 1: I found DT_HIDEPREFIX in DrawText() and using Custom Draw there is the CDIS_SHOWKEYBOARDCUES flag. However with Owner Draw I'm not sure if there is a flag someplace?
2 - How do you draw an icon for a button that is disabled to match what default buttons do?
TIA!!
For shortcut underline you can use WM_QUERYUISTATE to ask if it should be hidden or visible
DWORD draw_text_flags = ...;
if ( SendMessage( control_hwnd, WM_QUERYUISTATE, 0, 0 ) & UISF_HIDEACCEL ) != 0 )
{
// hide prefix
draw_text_flags |= DT_HIDEPREFIX;
}
// some combination of PBS_DEFAULTED, PBS_DISABLED, PBS_HOT, PBS_NORMAL, PBS_PRESSED;
int state = ...;
DrawThemeText( theme, hdc, BP_PUSHBUTTON, state, text, text_len, draw_text_flags, 0, rect );
Answer to Q2: If you create an HIMAGELIST using ILC_COLOR32 | ILC_MASK, and use ILD_NORMAL|ILD_BLEND25 on ImageList_Draw() it gives the same look as windows default buttons for a disabled button.
Based on responses from #Remy-Lebeau and #Daniel-Sęk and reviewing various projects on CodeProject, I create an easy to use class to handle this. It can be found at CodeProject. Thanks Guys.

MFC CEdit input limits text to 10 characters on 4k resolution

I use a CEdit text field to input a search term in an MFC application. When using it on FullHD resolution it works fine, I can input as long as big of a string as i need, but when using on 4k resolution the text is limited to 10 characters. The return of GetLimitText is 3000, and if I SetLimitText to a value smaller than 10 it works, limiting to more (such as 20) doesn't do anything, only 10 characters can be input still. Has anyone had this problem before or it might be from my implementation?
I "fixed" it in a way. I was calling CWnd::ModifyStyleEx(0, WS_EX_CLIENTEDGE). I replaced with CWnd::ModifyStyle(0, WS_BORDER). This is not a true fix as it changes the way it looks a bit, but I guess this is a bug.
I ran into a similar problem when creating the equivalent of resources for a CDialogBar on-the-fly (instead of using the resource editor). One of the controls was a CEdit control, and as user3808318 pointed out, MFC or Windows mysteriously ignores any value you assign using SetLimitText, and seems to ignore any characters you type that would extend beyond the edit control on the screen.
This is the original way that I created the edit control that resulted in this problem.
Create (WS_CHILD | WS_VISIBLE | WS_BORDER, rectDummy, this, IDC_FIND_TEXT)
Here is the correct way, now including the ES_AUTOHSCROLL option.
Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, rectDummy, this, IDC_FIND_TEXT)

Remove border from win32 button

I have a button which is created in the WM_CREATE function of a Win32 Application with the following code:
hChangeWorldButton = CreateWindowEx(NULL,
"BUTTON",
"OK",
WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
2,
2,
25,
25,
hWnd,
(HMENU)CHANGEWORLD_BUTTON,
GetModuleHandle(NULL),
NULL);
SendMessage(hChangeWorldButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)worldBmp);
I would like the button to show only the image. Not the background and border.
How can I do this? I have tried many different button styles from MSDN but nothing seems to fit my needs. I was thinking of using BS_OWNERDRAW but it seems a bit overkill. Or is it the only solution?
Finally, how can I change the cursor to be a hand when it's hovering over the button?
No button style is available that results in the visual representation you are after. You would have to go with BS_OWNERDRAW here.
As an alternative you could use a Static Control with the SS_NOTIFY style instead. A static control allows you to get the visual representation you want, and the SS_NOTIFY styles allows you to respond to mouse input. However, you will not be able to implement a keyboard interface.
While I have not tried this myself, it may also be possible to get the desired effect by using a Command Link (BS_COMMANDLINK), and setting the caption to an empty string.
To eliminate the button's background and border simply make the button smaller than the bitmap.

Transparent text box

I would like to use a transparent read-only text box as a replacement for a label; to allow users to select+copy the text. Exactly what Windows Explorer uses on the file properties window:
I've found similar question: Making a TextBox Transparent
Comments there suggest that proposed solutions do not work with ClearType. But my testing of suggested "AlphaBlendTextBox - A transparent/translucent textbox for .NET" component shows otherwise.
Anyway, the code looks quite complex for such a "simple task". They do save parent control image to a bitmap, drawing that bitmap over and over again with the text on top of it. I would expect there there has to be a solution delegating drawing of the background to parent control.
Possibly their solution is that complex because it allows alpha-blending too. I do not need that. I just want to see a parent background behind the text. Is there a simpler/smarter way?
Note that I'm happy with any winapi solution (pure winapi, MFC, WinForms, Delphi, whatever).
According to Spy++, it's a typical Edit control with WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOPARENTNOTIFY as extended style and WS_CHILDWINDOW | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL | ES_READONLY as original window style.
I've tested it in Win32 and I can confirm that it does what you want it to do.
Also, next time you want to mimic the appearances of other controls, simply fire up Spy++ to get the detailed information about them.

Removing window frame / border properly

I've been working on a custom GUI framework since I just can't deal with managed crap or native code which requires development of UIs through markup (XAML). I am trying to create a prototype of an application which uses that GUI framework, but I am having a platform-specific issue with the nature of windows within WinAPI.
The DWM doesn't really allow customization of the non-client area which breaks immersion, the only thing it allows is extension into the client area in order to give an illusion of customization.
So, the best course of action is to reconstruct the "non-client area" within the client area (relative to WINAPI) and that required me to strip the caption, maximize, minimize buttons etc. So, I basically enumerated all the things I want out and OR-ed them together and flipped all the bits in order to deactivate them.
~(WS_CAPTION | WS_SYSMENU | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZE | WS_MAXIMIZE | WS_THICKFRAME)
Once these style go away, I cannot use normal shutdown procedures (Alt+F4, or right clicking in the taskbar and going "Close") because they don't work. I had to intercept VK_ESCAPE and PostQuitMessage(0) manually just so I could exit without being forced to kill the process.
Why is this so? And how can I fix this?
The short answer
Replace:
~(WS_CAPTION | WS_SYSMENU | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZE | WS_MAXIMIZE | WS_THICKFRAME)
With:
WS_POPUP
And no more funky behavior. The application responds correctly. Enjoy the cake.
The long answer
Ah, as with everything on MSDN lately, the cake is a lie. Window styles are not really just visual. They also specify what inherent window functionalities are available to the application's window(s). Now, there is a fair amount of trickery here to be observed.
First of all, the MSDN isn't really forthcoming and useful with its window style definition table. The default behavior for windows is the classic caption, close, border package which is identified as the WS_OVERLAPPEDWINDOW which occupies the simplest expression, 0 (a 32-bit value, all bits down, 0x00000000), so someone wishing to rush through things could just set 0 for styles in the CreateWindow* function and it would yield a classic window.
What you want is a bare-bone, dirty and empty window. And Microsoft's got exactly the thing you're looking for - WS_POPUP which sets the highest bit to 1 and everything else is 0. This will drop all the fancy resizing automata, window captioning and the cute minimize, maximize and close buttons.
Which means you're going to have to reimplement everything. But that's what you're going for, right?
Just flipping all the bits isn't enough, you will drop the wanted options, but also activate the rest of the options resulting in the application acting funny, what you're experiencing right now. Therefore, you either AND it with something else or use something readily defined by Microsoft - WS_POPUP.
And again. Enjoy the cake and happy coding.

Resources