Above is an image of an inner form (from the C++ project below) before and after I dragged it a little bit up and left to obscure the title bar, then back to the original position. You can see the title, icon, close/minimize buttons were not painted correctly. The same thing happens in Foxpro and VS 2005.
In my prior post, Fix your forms to paint borders correctly under Vista Aero, I showed how Vista Aero doesn’t allow a window that already exists to change its border unless running as an Administrator.
If you run VS 2005 on Vista with Aero as a non-administrator, you can reproduce the same problem with the Windows Form Designer:
Start VS 2005, choose File->New->Visual Basic->Windows Application
Click on the form in the Form designer to select it, then change the FormBorderStyle property to FixedSingle
Now hover your mouse over the ToolBox to make it appear over the form in the designer. Then move your mouse away to let it disappear (or cause any other VS Window to cover the form).
You’ll see that the Titlebar of the form doesn’t get painted correctly: remnants of the toolbox still exist on the title bar. It works fine running VS as Administrator, Vista without Aero, or Windows XP.
I didn’t install C# on this recently borrowed Vista Aero machine, so I can’t test it, but I suspect it’s the same behavior because it’s the same form designer.
Here’re a few lines of sample C++ code that isolates the problem. (Zip file of VS2005 project with EXE available here)
The program simulates a form designer: it creates a child window with a caption initially, turns off the caption, then turns it back on.
Note that for Windows Styles, WS_CAPTION = WS_BORDER | WS_DLGFRAME
Start VS 2005: choose File->New Project-> Visual C++ Win32 Win32 Project. Call it VistaPaint
In the Win32 Application Wizard, just choose all the defaults and Finish.
Add these lines after this line #include "VistaPaint.h",
class CForm2 : public CWindowImpl<CForm2>
DECLARE_WND_CLASS_EX(L"CForm2", 0, COLOR_MENUHILIGHT) // backcolor
and in the WndProc, add this case in the Switch to handle the WM_CREATE message:
CForm2 *pCForm2 = new (CForm2);
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
, /*WS_EX_DLGMODALFRAME |*/ WS_EX_WINDOWEDGE | WS_EX_NOPARENTNOTIFY);
SetWindowLong(pCForm2->m_hWnd, GWL_STYLE, GetWindowLong(pCForm2->m_hWnd, GWL_STYLE) & ~( WS_CAPTION | WS_SYSMENU) ); // turn off caption (WS_CAPTION = WS_BORDER | WS_DLGFRAME )
SetWindowLong(pCForm2->m_hWnd, GWL_STYLE, GetWindowLong(pCForm2->m_hWnd, GWL_STYLE) | ( WS_CAPTION | WS_SYSMENU) ); // turn on caption (WS_CAPTION = WS_BORDER | WS_DLGFRAME )
Last, change the InitInstance code to add the WS_CLIPCHILDREN flag: Change the CreateWindow line in InitInstance from
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN ,
Now hit F5 to run the code. Move the inner window inside the outer to cause the border to repaint. Observe the border doesn’t get repainted.
Now run the same app as an Administrator (start Windows Explorer, navigate to the Project Debug directory, right click on the EXE file and choose Run as Administrator). Observe that the border paints correctly.
For even more fun, comment out the DECLARE_WND_CLASS_EX line!