Remove border from win32 button - winapi

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.

Related

Displaying a tooltip with an icon

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;

Child Window Z-Order

I see in MSDN, it says:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
If the created window is a child window, its default position is at the bottom of the Z-order. If the created window is a top-level window, its default position is at the top of the Z-order (but beneath all topmost windows unless the created window is itself topmost).
However, another documentation says:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632599(v=vs.85).aspx
When an application creates a window, the system puts it at the top of the z-order for windows of the same type
I tested it like this:
btn1 = ::CreateWindow(L"button", L"OK", WS_TABSTOP|BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD
, 10, 10, 50, 30, hWnd, (HMENU)51, hInst, NULL);
btn2 = ::CreateWindow(L"button", L"Cancel", WS_TABSTOP|WS_CHILD|BS_PUSHBUTTON|WS_VISIBLE
, 20, 20, 70, 30, hWnd, (HMENU)52, hInst, NULL);
I created two buttons in a window and they overlapped, I can see that the button created later is covering the first button created.
Is the first statement in MSDN contradictory to my testing?
The documentation is accurate. You are being tripped up by another problem, you allow the child windows to draw themselves across other child windows. So now the painting order matters.
You fix that by adding the WS_CLIPSIBLINGS style flag to your CreateWindowEx call. You'll now see that the OK button is on top. Fix:
btn1 = ::CreateWindow(L"button", L"OK",
WS_TABSTOP|BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
10, 10, 50, 30, hWnd, (HMENU)51, hInst, NULL);
// etc, use it as well on other child windows
You should not rely to much on the how the child windows are displayed and which one is drawn last. If I run your sample code I get an OK button which is overlapped by the Cancel button. If I move the mouse over the buttons then the OK button comes into foreground and draws over the Cancel button.
I once had similar trouble with overlapping child controls. Then I found out that Microsoft says Overlapping Controls Are Not Supported by Windows.
BTW, if you really want to see the Z-order, then use GetTopWindow and GetNextWindow. Or the simpler way: run Microsoft Spy++.

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.

Windows 7 edit control, vertical scroll does not work

I have an application that compiles ok (mingw) and runs ok, however the edit control that is created has scroll bars but the vertical scroll bar doesn't do anything. The same executable works fine on WinXP. Also, the edit control has both vertical and horizontal scroll bars, the horizontal works just fine, but vertical does not. The vertical scroll bar is visible and clickable, but nothing happens...
Following code is used when creating the edit control:
HWND hwndEdit = CreateWindow(TEXT("EDIT"), TEXT("Edit control"),
WS_OVERLAPPED | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_READONLY | WS_SIZEBOX,
1000, 480, 400, 500, NULL, 0, GetModuleHandle(NULL), NULL);
SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM) TEXT(""));
SendMessage(hwndEdit, EM_LIMITTEXT, 0, 0);
Following code is used repeatedly to add text to edit control:
char test[] = "test";
SendMessage(hWndDbg, EM_SETSEL, 0x7FFFFFFF, 0x7FFFFFFF); // Undo any selection and move to end.
SendMessage(hWndDbg, EM_REPLACESEL, 0, (LPARAM) temp);
Finally found the fix. It seems in WinXP the edit control does not have to have a parent window defined, in Win7 it is required for the vertical scroll bar to work, horizontal scroll bar works in Win7 even without parent window defined.
Note that vertical scroll bars even make sense on single-line edit controls. In this case, WM_VSCROLL must be set, and ES_AUTOVSCROLL not. (EM_AUTOVSCROLL means EM_AutoHIDEVScroll.) The alternative UpDown control makes more programming efford than capturing VM_VSROLL messages, and then changing the (typically numerical) value inside the edit control.
Unluckily, the MS Visual Studio built-in Resource Editor won't let you add WM_VSROLL to single-line edits! You must do this by adding this bit by editing the .RC file in text mode.
Similar to the fact that this Resource Editor won't let you add a default text to the control, which is still supported by the resource loader.
Use GetDesktopWindow() as hWndParent parameter. It works on Win7.

Using CreateWindow and adding buttons and such to it? How?

I have realised after so long of coding DirectX/OpenGL applications I don't have the faintest of ideas how to create windows with basic form objects like text boxes, labels, command buttons etc.
I can create a window using the CreateWindow function just fine, how can I add buttons, command prompts and other form objects to it?
Look at Create Window Help. Once you create your main window you can create child windows by providing the parent HWND to the function. For standard controls you use one of the class names defined at the button, like EDIT for an edit box and BUTTON for a button.
As an example: CreateWindow(L"BUTTON", L"Button", BS_TEXT | WS_CHILD | WS_VISIBLE, 40, 40, 100, 40, hMainWnd, (HMENU)ID_MYBUTTON, hInstance, NULL);
Or you could just create a dialog box instead and edit it with Visual Studio's resource editor (if you have full VS that is).

Resources