Opening a Window That Has No Title Bar with Win32

Opening a window that has no title bar with Win32

hWnd = CreateWindow(szWindowClass, 0, (WS_BORDER ), 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); 

SetWindowLong(hWnd, GWL_STYLE, 0); //remove all window styles, check MSDN for details

ShowWindow(hWnd, SW_SHOW); //display window

Created windows have no title

I am posting the answer to the question as suggested by a comment :
The answer is that for the window creation to complete, the pWndProc passed to RegisterClass WINAPI has to process default messages (in particular OS messages).
During the execution of CreateWindow(after the call has started and before it has returned), the pWndProc function already receives messages that it has to process, in my case it didn't process them.
This is a standard pWndProc function:

LRESULT CALLBACK pWndProc(HWND hwnd,            // Handle to our main window
UINT Msg, // Our message that needs to be processed
WPARAM wParam, // Extra values of message
LPARAM lParam) // Extra values of message
{
switch (Msg)

{
case WM_DESTROY:
...
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
}

source :

A window procedure does not usually ignore a message. If it does not process a message, it must send the message back to the system for default processing. The window procedure does this by calling the DefWindowProc function, which performs a default action and returns a message result. The window procedure must then return this value as its own message result. Most window procedures process just a few messages and pass the others on to the system by calling DefWindowProc.

WinAPI: Create resizable window without title bar, but with minimize/maximize/close buttons (as Firefox/Chrome/Opera)

The programs remove the non-client area (the title bar) and have a bunch of custom handling for reproducing the window buttons, icons, system menu etc. The benefit of this is that they can draw to the new "title bar", which is actually part of the standard client area, adding tabs or other custom controls.

The following two articles will show you how to do this on Vista and above (using the DWM):

  • Setting up a custom title bar on Windows Vista / 7
  • Setting up a custom title bar - reprise This one has a demo app showing the result of a number of variations / options.

This is very complex to do and get right, so the above two articles are invaluable. The author must have put a lot of work into them! Both links have example code written in Delphi, but it should be easy enough to translate it to C++ - the concepts are identical, it's just syntax.

You might also be interested in general resources on Glass and DWM, since it's all closely related. You'll spot the above two links included in that list :)

Prevent Win32 from drawing classic title bar

Big thanks to @Erik Philips, I have finally resolved the issue by following this answer's advice. The issue was in CreateParams:

/// <summary>
/// Gets the parameters that define the initial window style.
/// </summary>
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
if (!DesignMode) {
cp.ClassStyle |= (int) ClassStyle.DoubleClicks;
cp.Style |= unchecked((int) (WindowStyle.Popup | WindowStyle.SystemMenu | WindowStyle.ClipChildren | WindowStyle.ClipSiblings));
cp.ExStyle |= (int) ExtendedWindowStyle.Layered;
}
return cp;
}
}

The | had to be removed from cp.Style:

protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
if (!DesignMode) {
cp.ClassStyle |= (int) ClassStyle.DoubleClicks;
cp.Style = unchecked((int) (WindowStyle.Popup | WindowStyle.SystemMenu | WindowStyle.ClipChildren | WindowStyle.ClipSiblings));
cp.ExStyle |= (int) ExtendedWindowStyle.Layered;
}
return cp;
}
}

This solved the issue, as apparently WinForms adds WS_BORDER by default to the class style, even if FormBorderStyle is later set to None.

Removing the Title bar of external application using c#

No need to inject anything, you can just modify the windows style bits as using the API, e.g. this works for Notepad, however YMMV depending on the app you're playing with.

alt text

//Get current style
lCurStyle = GetWindowLong(hwnd, GWL_STYLE)

//remove titlebar elements
lCurStyle = lCurStyle And Not WS_CAPTION
lCurStyle = lCurStyle And Not WS_SYSMENU
lCurStyle = lCurStyle And Not WS_THICKFRAME
lCurStyle = lCurStyle And Not WS_MINIMIZE
lCurStyle = lCurStyle And Not WS_MAXIMIZEBOX

//apply new style
SetWindowLong hwnd, GWL_STYLE, lCurStyle

//reapply a 3d border
lCurStyle = GetWindowLong(hwnd, GWL_EXSTYLE)

SetWindowLong hwnd, GWL_EXSTYLE, lCurStyle Or WS_EX_DLGMODALFRAME

//redraw
SetWindowPos hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_FRAMECHANGED

Hide Title Bar of Program using API

This simple app hides and shows the title bar of the console that it's in. It changes the console title to a guid momentarily to find the window handle. Afterwards it uses ToggleTitleBar to show or hide using the found handle.

public class Program
{
public static void ToggleTitleBar(long hwnd, bool showTitle)
{
long style = GetWindowLong(hwnd, -16L);
if (showTitle)
style |= 0xc00000L;
else
style &= -12582913L;
SetWindowLong(hwnd, -16L, style);
SetWindowPos(hwnd, 0L, 0L, 0L, 0L, 0L, 0x27L);
}

public static void Main()
{
Guid guid = Guid.NewGuid();
string oldTitle = Console.Title;
Console.Title = guid.ToString();
int hwnd = FindWindow("ConsoleWindowClass", guid.ToString());
Console.Title = oldTitle;

Console.WriteLine("Press enter to hide title");
Console.ReadLine();
ToggleTitleBar(hwnd, false);
Console.WriteLine("Press enter to show title");
Console.ReadLine();
ToggleTitleBar(hwnd, true);
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}

[DllImport("user32", EntryPoint = "GetWindowLongA")]
public static extern long GetWindowLong(long hwnd, long nIndex);

[DllImport("user32", EntryPoint = "SetWindowLongA")]
public static extern long SetWindowLong(long hwnd, long nIndex, long dwNewLong);

[DllImport("user32")]
public static extern long SetWindowPos(long hwnd, long hWndInsertAfter, long x, long y, long cx, long cy,
long wFlags);

[DllImport("User32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
}


Related Topics



Leave a reply



Submit