C++ how to display text in child window at real time - c++

This application creates a child window (which is the white box) when I right click anywhere, and destroys the child window after another right click. I have implemented the mechanics to expand and shrink the red rectangle through Direct 2D. I would like the child window to display the width and height of the rectangle at real time, as I make changes to it. I do not interact with the child window at all: it doesn't need an "x" button for closing and stuff; it just prints out a couple lines of data.
Here is what I have in my main window procedure:
case WM_RBUTTONUP:
{
DemoApp *pDemoApp = reinterpret_cast<DemoApp *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
pDemoApp->showTextBox = !pDemoApp->showTextBox; //showTextBox is a boolean
if (pDemoApp->showTextBox) {
POINTS cursor = MAKEPOINTS(lParam);
pDemoApp->child_hwnd = CreateWindowEx(
WS_EX_TOPMOST,
"LISTBOX",
"I dont need a title here",
WS_CHILDWINDOW,
cursor.x,
cursor.y,
100,
200,
pDemoApp->main_hwnd,
NULL,
HINST_THISCOMPONENT,
pDemoApp
);
ShowWindow(pDemoApp->child_hwnd, SW_SHOWNORMAL);
UpdateWindow(pDemoApp->child_hwnd);
}
else {
DestroyWindow(pDemoApp->child_hwnd);
}
}
break;
How may I go from here? I would like to know:
Is using Direct Write to draw text in the child window my only option? I see the dashed lines in the white box so I assume there must be a way to display plain text.
I used LISTBOX here, which is a predefined windows class name. How do I set a procedure for it? What else predefined class name can better suit my need? Or do I have to register a custom one;
I would like to drag the child window around, how can I set it up so that the system handles dragging for me.
Would popping a dialog box to display text be better than popping a child window?
Thanks.

Since you are using a Win32 LISTBOX control as the child window, then you have a couple of options for displaying the rectangle's dimensions in it:
give the ListBox the LBS_HASSTRINGS style, and add 1-2 items to it. Then, any time you change the rectangle, send LB_DELETESTRING and LB_ADDSTRING messages to the ListBox's HWND to display the updated dimensions as needed. A ListBox does not have a way to update an existing item, so to change an existing item's text, you have to remove the item and then re-add it with the new text.
give the ListBox an LBS_OWNERDRAW... style, and add 1-2 blank item(s) in it. Then have the ListBox's parent window handle WM_MEASUREITEM and WM_DRAWITEM notifications from the ListBox to display the rectangle's current dimensions in the item(s) as needed. Whenever the rectangle is changed, call InvalidateRect() on the ListBox's HWND to trigger a redraw.

Related

Child Windows that does not occupy client area

In the Win32 API (pure win32), The Menu bar does not occupy any area from the client area of the window. Which means the origin coordinates of the client area is right under the menu bar to the left.
When we create child window controls using CreateWindow (or any other method), that window takes some area of the client-area.
eg:- Creating a button which is at (xPos = 0, yPos = 0) and (width=width_of_client_area, height=20).
After creating the button if you'll use a GDI function like this, it'll be drew below the button:
Rectangle(hdc, 0,0, 200, 200);
But when creating a menu bar, it doesn't occupy client area. (GDI will not be drew under menu).
FINAL QUESTION:
How can i create a control on my parent window like the menu bar ?
The menu is rendered in the non-client area of the window, which is driven by a completely different set of window messages. Keep in mind that you don't actually create child windows for these types of controls. You will need to provide all the rendering and event handling for the customization you want to add. This means that if you want to add a button or checkbox you will need to implement it yourself. You can get your started with a handful of steps but there may be other things that need to be done depending on your requirements.
The first step is to process the WM_NCCALCSIZE message. This will allow you to adjust the size of the non-client area so that you have more space to draw the custom control. Basically you will pass this message on to the default window proc then modify the location and dimensions (just drop the top down X pixels) before returning.
The next step is to handle WM_NCPAINT message. Pass the message on to the default window proc then draw your custom visuals in the area you have reserved. You will be working with a window DC so you can draw to the entire window. It's important to keep this in mind so you don't destroy anything in the client area.
The last item that needs to be done is to handle mouse messages like WM_NCMOUSEMOVE. If the mouse event occurs outside the area where your control is located pass the message to the default window proc, otherwise handle the message yourself and skip the default proc. you will need to manage some state data for keeping track of when a button is down or not so as not to cause conflicts with the default window proc.
Keep in mind that when you want to draw directly to the non-client area you need to call GetWindowDC() instead of GetDC() to acquire a device context.
[Note: A good Google dance will be something like "WinAPI non-client area"]

split a window without a split bar

In order to split a window into 2, for example, viewing 2 documents at the same time, we created 2 child windows and a split bar to resize the child windows.
But I have seen many applications which have multiple panels without a split bar. In fact, there is a 'line' between the panels, but I found that they created an extra child window hwndChild1Container which contains the first child window hwndChild1 and the size is a litte wider than hwndChild1, hence there is a bar as we see.
My question is: In order to do the same thing, I don't know which window style I have to use for hwndChild1Container. I don't want hwndChild1Container has a board like the main window, but I need it being resizeable and when the mouse is over the right boarder, the cursor changes the shape like the case for main window. Is there a build-in window style for such child window, or I have to do this manually in the window procedure of hwndChild1Container?
Container does not need any special styles. Just process WM_NCHITTEST for container and return HTBOTTOM for bottom pixels.

Custom button shape

I want to implement a simple volume up/down button using a custom bitmap, and all it's going to have is a simple hover effect, and mouse down effect.
My first idea was to process WM_MOUSEMOVE for the hover, and process WM_LBUTTONUP and WM_LBUTTONDOWN for the mouse down effect.
First, is this the easiest way to do this? I could superclass a button and just paint the bitmap and forget about the text...
Then I have the problem with the background, which should be transparent, I know I can use a mask by passing SRCAND to BitBlt, but this requires me to have 2 images for each button. Is there any way to do this with just one image? Like if I put a green background on it in my image editor, could I mask that out with a green screen like effect?
You need to create a regular button, and subclass it with SetWindowSubclass. The button must have the owner-draw style on it, which means in the parent WndProc, you are handling WM_DRAWITEM. As you correctly say, you will be BitBlt'ing or StretchBlt'ing the background of the image on.
For hover events you must do the following:
Have some sort of shared boolean between the parent and subclassed WndProc, eg. IsMousedOver
In the subclassed WndProc, process WM_MOUSEMOVE. When this message is hit, you should set IsMousedOver, then invalidate the control with InvalidateRect (this will trigger WM_DRAWITEM in the parent)
In the parent WndProc, if you receive WM_MOUSEMOVE, you should clear IsMousedOver
In WM_DRAWITEM in the parent WndProc, you should check IsMousedOver and BitBlt based on that state
If you want to process MouseUp/MouseDown, you can change the boolean to an int instead and have a tri-state. However, most implementations have MouseDown being the same as the regular button, and MouseUp is then simply the regular moused over background.
As for your query about 2 images, it may well be possible to do it with one but I haven't tried that before.

Bona fide transiant windows with WinAPI?

I want to create a Window like when a context menu pops up or clicking the menubar. I want a Window that will be like this and that I can take over its paint event. Sort of like what is created when you select a sub tool in Photoshop.
EDIT:I want to know how to create controls like the one that comes when you select a sub tool in Photoshop, these do not seem to have a parent window. Those little description popups are a good example of this type of window, and menu items, those rectangles have no parent window.
Thanks
EDIT2: see this: http://cdn-viper.demandvideo.com/media/CB3C805F-421E-45AE-8359-39D59D8F0165/jpeg/20412728-192C-462A-AF8E-1F30BA77AE05_2.jpg
You will notice the window for the sub tools, it is not constrained to a parent window.
But how do they get a nice shadow
around it, and how does it still stay
with the main window without a parent?
That's your real question.
There are several ways of getting the shadow. One is that the window is actually two windows, the "shadow" plus the "main" window.
When you create the flyout window (that's what it's called), you position it near the toolbar. If the toolbar gets a WM_MOVE message, it's your responsibility to call MoveWindow() on the flyout to keep it lined up.
Edited to add
The dwExStyle parameter of CreateWindowEx() should include WS_EX_LAYERED and probably WS_EX_TRANSPARENT, because the 'shadow' will use alpha blending. The hWndParent parameter is the application's main window. The x and y parameters must be calculated as an offset of whatever button the window is to be associated with.

Use DrawText to update label

I am currently writing a program in c++ (no MFC) and want to update a label (win32 static control) using the win32 DrawText function. However when i call the function nothing is written to the label. I use the following code:
HDC devCon = ::GetDC(GetDlgItem(IDC_TITLE).m_hWnd);
RECT rect = {10, 10, 100, 15};
::DrawText(devCon, _T("TEST DC TEXT!!!"), -1, &rect, DT_NOCLIP);
::ReleaseDC(GetDlgItem(IDC_TITLE).m_hWnd, devCon);
As you see with the GetDlgItem(...) I am using ATL but that should not be a problem in my opinion. When I specify NULL in the GetDC method the text is drawn in the upper left corner of the screen as it is supossed to be since the method return the DC to the entire screen.
Why doesn't this work with the DC of the label?
Hope you folks can help me.
If you want to draw the text manually because setting the control text doesn't do what you want, then you need to tell Windows that you're doing that. Otherwise the control will draw itself over whatever you do whenever it needs to be redrawn.
To draw it yourself, mark your control as owner draw by setting the SS_OWNERDRAW style, and then handle the WM_DRAWITEM message to draw it in the window procedure of the parent window, or subclass the window and handle the WM_PAINT message in your new window procedure.
I guess that the text is drawn but at the next window message is set to the default text.
Try to set the text with SendMessage(..,WM_SETTEXT,...);
Use SetDlgItemText() to set the text for the control.
You are trying to paint directly onto the static control's device context.
This is not going to be so simple, because:
the control will repaint itself whenever it's update region is invalidated
usually the controls share the device context with the parent window, so what you are getting in GetDC(...) is actually your dialog's device context.
So, use SetDlgItemText, or SetWindowText to set the text of the window.
To use a custom font (or set the text/background color), handle the WM_CTLCOLORSTATIC message in your WindowProc.