Etched border (Win32) - winapi

I'm looking for a way to get an etched border style for a window under win32. I have tried DrawEdge with the EDGE_ETCHED flag, which does give me that, but I'm not sure how obtain the same style for a scrollable window. SetWindowLong with GWL_EXSTYLE and WS_EX_STATICEDGE gives me something close, but I haven't found any other style flags that yield a different border. So is this effect even possible?
Thanks in advance,
Christopher

You can do that sort of thing by handling WM_NCPAINT and other WM_NCxxx messages.
The NC stands for "Non Client area" of the window. The normal drawable area returned in the Device Context (DC) from BeginPaint is clipped to the "client area" of the window.

Related

Is there any Windows API that can "normalize" or "maximize" a window?

I was using Ruby's Win32API to MoveWindow to move a window and resize it.
But if the window is minimized, it won't show.
SetWindowPos works too, and has a flag to hide or show the window, but it is to only make a window visible or invisible, not about minimizing or normalizing.
I also tried SetForegroundWindow and SetActiveWindow and they won't work either. Is there a call to make a window normalized or maximized?
ShowWindow(hwnd, SW_RESTORE) may be what you're looking for. See: MSDN docs

How do I get the paintable area in a CFrameWnd with dialog bars?

I have a CFrameWnd with a dialog bar, and I'd like to determine the paintable area (excluding the space used by the dialog bar) so I can draw in it without being overlapped by the dialog bar. How can I do this? GetClientRect() seems to cover the client rect area as well, and I don't see any other obvious candiates in the doucumentation.
I'm pretty sure the Cwnd::RepositionBars method should provide the information you need. Does the following code work for you?
CRect rcClient;
pFrameWnd->RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0, CWnd::reposQuery, &rcClient);
I had a similar problem with CDockablePane which I solved with
CRect rc;
GetDockingManager()->GetClientAreaBounds(rc);
but I also ran into the problem of not being able to find a message or callback to know when to trigger it.

Taking a screenshot of the window in the background

Will it be any problems to take a screenshot of the window content, if that window is overlapped by some other application.
This is possible / easy with PrintWindow (user32.dll). For a detailed code example, see Capturing Windows Regardless of Their Z-Order.
Unless you've got a method in the application to render it to an off-screen bitmap you'll only get the visible portions of the window.
You could hide the top window, then do the screenshot.
In autohotkey: use winhide:
WinHide, window_name
your snapshot code here, then
WinShow, window_name

Pure win32 cross-process child windows

I need to create a transparent overlay window, that goes above another window. The other window is from another vendor. And when the user drags that window mine needs to follow.
WS-CHILD seems like a nice idea but it cannot be combined with WS-EX-LAYERED, which I really need (for transparency). But I still can set a parent without using WS-CHILD.
Parenting does give my winproc notifications (WM-WINDOWPOSCHANGING), but only after dragging is complete, on mouse-up. To give a nice feeling i need to get those notifications (or for example WM-MOVE) continuosly while dragging.
I guess my problem is similar to docking, but the fine docking solution seen fx at CodeProjet uses WS-CHILD. ( http://www.codeproject.com/KB/toolbars/dockwnd.aspx )
I guess I could use polling but that is not what I am looking for. Also I could use ::SetWindowsHook(). But that is my final resort. I am hoping I have missed something trivial and that somebody can point me in a good direction.
Thanx
I know it is not your preferred solution, but I think you need to use a global mouse hook. Pass WH_MOUSE_LL to SetWindowsHookEx() and do nothing in the default case of your low-level mouse proc. But when you get the WM_WINDOWPOSCHANGING notification, start tracking the mouse movements and making appropriate calls to MoveWindow() or whatever.
I use a LayeredWindow for that and set the other window as parent.
This is the code I used for that:
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, GetWindowLong(GetHwnd(), GWL_EXSTYLE) |WS_EX_LAYERED);
::SetLayeredWindowAttributes(GetHwnd(), RGB(255,0,255), 255, LWA_COLORKEY | LWA_ALPHA);
::SetWindowLongPtr(GetHwnd(),GWLP_HWNDPARENT,(long)GetParentHWND());
::SetWindowPos(hndOtherWindow, hndOverlayWinow, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |SWP_NOACTIVATE);
It works for my purposes. There's only one problem left: If my overlaying window loses the focus I want to set the focus, or activate the other window. Do you have an idea?
How about WM_MOVING message? You may try intercepting this message and move your window accordingly.
If you want to know when a window in another process is being moved or sized, you need to install a hook,catch the WM_MOVING and WM_SIZING messages and reflect those messages back to your controller process. Sorry it's not the answer you want! I don't blame you for wanting to avoid cross process hooks, its a bit of a pain...

How to avoid flicker while handling WM_ERASEBKGND in Windows dialog

I have a dialog that resizes. It also has a custom background which I paint in response to a WM_ERASEBKGND call (currently a simple call to FillSolidRect).
When the dialog is resized, there is tremendous flickering going on. To try and reduce the flickering I enumerate all child windows and add them to the clipping region. That seems to help a little -- now the flickering is mostly evident in all of the child controls as they repaint.
How can I make the dialog flicker-free while resizing? I suspect double-buffering must play a part, but I'm not sure how to do that with a dialog with child controls (without making all child controls owner-draw or something like that).
I should note that I'm using C++ (not .NET), and MFC, although pure Win32-based solutions are welcomed :)
NOTE: One thing I tried but which didn't work (not sure why) was:
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.FillSolidRect(rect, backgroundColor);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
Assuming that "FillSolidRect" is the erase of your background then return TRUE from the WM_ERASEBKGND.
To do the double buffering that you are almost doing in your code fragment, you will need to use CreateCompatibleBitmap and select that into your memDC.
Try adding the following line to your OnInitDialog function:
ModifyStyle(0, WS_CLIPCHILDREN, 0);
Do nothing in the WM_ERASEBKGND handling and do the erase as part of your main WM_PAINT. You can either paint smarter so that you only redraw the invalid areas, or more easily, double-buffer the drawing.
By not doing anything in the erase background, you have all your drawing code in one location which should make it easier for others to follow and maintain.
If you are targeting WinXP or higher, you can also use the WS_EX_COMPOSITED style to enable double-buffering by default for top-level windows with this style. Bear in mind this has its own set of limitations -- specifically, no more drawing out of OnPaint cycles using GetDC, etc.
you can set parameter of your call to InvalidateRect method as false. This will prevent you to send WM_ERASEBKGND when the window will redraw.
Double buffering is indeed the only way to make this work.
Child controls will take care of themselves so long as you make sure CLIPCHILDREN.

Resources