你能在Windows中创建一个没有WS_POPUP样式的无边界应用程序主窗口吗?

时间:2011-02-04 19:11:35

标签: delphi winapi visual-c++

我想创建一个窗口,它将成为主窗口,Windows本身将其识别为主应用程序窗口。但是,当我使窗口无边框,并且根本没有任何非客户区域时,Windows不再认识到该窗口是应用程序主窗口。这有几个副作用:

  1. WindowsKey + M最小化除应用程序主窗口之外的所有窗口。

  2. 在任务栏上单击一次(在win7中),然后再次,应该在正常状态和最小化状态之间切换应用程序主窗口的状态/可见性。这对于这样的窗口不起作用。

  3. 在简单的Win32编程术语中,我在调用dwStyle(WS _...常量)或CreateWindowEx(WS_EX _...常量)时询问CreateWindow的参数值。对于delphi用户,这些值将在您将覆盖的CreateParams方法中设置,然后设置Params.Style:= WS_xxx;对于MFC / C ++用户和C用户,框架中的某些内容最终将使用此dwStyle值调用CreateWindow。

    在delphi术语中,设置form.BorderStyle = bsNone,得到dwStyle = WS_POPUP。但是我想要一个不使用dwStyle = WS_POPUP的无边框窗口。

    注意:下面的所有答案都很好,但在生产场景中使用每个答案都有问题,而且我尝试这样做,导致遇到很多故障,对于专业质量的应用程序,我仍然发现我无法解决。戴维斯的答案是一个很棒的纯Win32 API答案,并且符合要求。似乎工业强度解决方案应该结合多种品质,包括我在上面的问题中所具有的所有品质。简而言之,使用BorderStyle = bsNone(dwStyle = WS_POPUP)的无边框表单会阻止通常应用于应用程序主窗口的所有Windows功能,并且下面的所有解决方案都可以解决部分问题。

    根据David的建议,我写了以下内容,但不起作用: 我想要一个没有边框的窗口,它在各个方面(如Windows应用程序窗口)对系统起作用,也就是说,可以通过单击任务栏中的窗口来最小化/恢复它,并且将通过WindowsKey + M最小化。我开始认为这样做的唯一方法是添加非客户端绘制代码并将顶部非客户区域边界调整为零。这当然不是一个微不足道的想法。

    事实证明,我在编码中犯了一个简单的错误(因此上面的两段),实际上下面的代码现在按照我的意愿工作。这个是pascal,但它应该很容易转换为C ++或其他任何东西。

    program NoBorderProject;
    
    uses
      Windows, Messages;
      {the Messages unit contains the windows
      Message constants like WM_COMMAND}
    
    {$R *.RES}
    
    var
      wClass: TWndClass;
      Msg: TMsg;
      win:HWND;
    function WindowProc(hWnd,Msg,wParam,lParam:Integer):Integer; stdcall;
    begin
     if Msg = WM_DESTROY then PostQuitMessage(0);
     Result := DefWindowProc(hWnd,Msg,wParam,lParam);
    end;
    
    begin
     wClass.lpszClassName:= 'CN';
     wClass.lpfnWndProc :=  @WindowProc;
     wClass.hInstance := hInstance;
     wClass.hbrBackground:= 1;
     RegisterClass(wClass);
     win := CreateWindow(wClass.lpszClassName,'Title Bar',
                  WS_POPUP,//WS_OVERLAPPEDWINDOW or WS_VISIBLE,
                  10,10,340,220,0,0,hInstance,nil);
     SetWindowLong(win, GWL_STYLE, WS_POPUP or WS_MINIMIZEBOX);
     SetWindowLong(win, GWL_EXSTYLE, 0 );
     ShowWindow(win,SW_SHOW);
     while GetMessage(Msg,0,0,0) do
       DispatchMessage(Msg);
    end. 
    

3 个答案:

答案 0 :(得分:13)

以下内容完成了工作:

hWnd = CreateWindow(...);
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_MINIMIZEBOX);
SetWindowLong(hWnd, GWL_EXSTYLE, 0);
ShowWindow(hWnd, ...);

你可能遗失了WS_MINIMIZEBOX

答案 1 :(得分:4)

有点icky,但您可以通过将其置于YourForm.OnShow事件中来设置窗口区域:

var
  r: TRect;
begin
  r := ClientRect;
  OffsetRect(r, 0, GetSystemMetrics(SM_CYCAPTION));
  OffsetRect(r, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
  SetWindowRgn(Handle, 
      CreateRectRgn(
          r.Left, r.Top, 
          ClientWidth + r.Left, ClientHeight + r.Top), True);

答案 2 :(得分:-4)

您需要覆盖TForm.CreateParams并设置或删除您感兴趣的任何样式

procedure TYourForm.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.Style := Params.Style and
  Params.ExStyle := Params.ExStyle or ;
end;