2011-02-04 12 views
8

Quiero crear una ventana que será la ventana principal y que Windows mismo reconoce como una ventana principal de la aplicación. Sin embargo, cuando configuro mi ventana sin bordes y sin ninguna área que no sea del cliente, Windows ya no reconoce que esta ventana es una ventana principal de la aplicación. Esto tiene varios efectos secundarios:¿Se puede hacer una ventana principal de la aplicación sin bordes en Windows, sin el estilo WS_POPUP?

  1. WindowsKey + M minimiza todas las ventanas excepto la ventana principal de mi aplicación.

  2. Al hacer clic una vez en la barra de tareas (en win7) y nuevamente, debe alternar el estado/visibilidad de la ventana principal de la aplicación entre el estado normal y el estado minimizado. Esto no funciona para esa ventana.

En términos de programación Win32 desnudas, yo estoy preguntando por los valores de los parámetros para dwStyle como cuando se llama a CreateWindow (WS constantes _...), o (constantes WS_EX _...) CreateWindowEx. Para los usuarios de delphi, estos valores se establecerían en el método CreateParams, que se anularía, y luego se configuraría Params.Style: = WS_xxx; Para usuarios de MFC/C++ y usuarios de C, algo en su marco eventualmente estaría llamando a CreateWindow, con este valor de dwStyle.

En términos delphi, estableciendo su form.BorderStyle = bsNone, resulta en dwStyle = WS_POPUP. Sin embargo, quiero una ventana sin bordes sin usar dwStyle = WS_POPUP.

Nota: Todas las respuestas a continuación son buenas, pero utilizar cada una de ellas en escenarios de producción es problemático y mis intentos han resultado en muchos fallos técnicos que, para una aplicación de calidad profesional, todavía encuentro que no puedo trabajar alrededor. Sin embargo, la respuesta de David es una gran respuesta API pura de Win32, y se ajusta a la perfección. Parece que una solución de fortaleza industrial debe combinar múltiples cualidades, incluidas todas las que tengo en mi pregunta anterior. En resumen, las formas sin bordes que usan BorderStyle = bsNone (dwStyle = WS_POPUP) bloquean todas las funcionalidades de Windows que generalmente se aplican a las ventanas principales de las aplicaciones, y todas las soluciones a continuación resuelven una parte de ellas.

Basado en las sugerencias de David, escribí lo siguiente, que no funciona: Quiero una ventana sin borde, que se comporte de todas las maneras, como una ventana de aplicación de Windows, en el sistema, es decir, puede ser minimizado/restaurado haciendo clic en la ventana en la barra de tareas, y será minimizado por WindowsKey + M. Estoy empezando a pensar que la única forma de hacerlo es agregar código de pintura que no sea cliente y cambiar el tamaño de los límites superiores de área no cliente a cero. Esto, por supuesto, no es una idea trivial.

Resulta que cometí un simple error en mi codificación (de ahí los dos párrafos anteriores) y, de hecho, el código siguiente funciona ahora como deseo. Este está en pascal, pero debería ser fácil convertirlo a C++ o cualquier otra cosa.

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. 
+1

Encontré su error. Estableces 'GWL_STYLE' dos veces. La segunda llamada a 'SetWindowLong' debería ser establecer' GWL_EXSTYLE'. –

+0

Aquí con D7, MainForm.BorderStyle = bsNone no impide que WinKey + M funcione. También minimizar/restablecer cambia completamente bien. ¿Podría esto atribuirse a la propiedad MainFormOnTaskbar de TApplication que está configurada de manera predeterminada en las versiones más nuevas de Delphi? – NGLN

+0

NGLN- Exactamente. Delphi 7 tiene una ventana de aplicación falsa de nivel superior y, por lo tanto, Windows no cree que su formulario sea la ventana principal de su aplicación, sino que utiliza el antiguo Delphi hack de una ventana principal especial oculta. Este comportamiento también es la raíz de los errores de orden Z inherentes al truco de formulario principal de la era Delphi 7. –

Respuesta

13

A continuación se hace el trabajo:

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

Probablemente faltaban WS_MINIMIZEBOX.

+0

Esto no funciona. Supongo que no puedes evitar el estilo 'WS_POPUP' si no quieres tener un borde. Pero quizás puedas hacer que la ventana se comporte normalmente * aunque * el bit 'WS_POPUP' esté ahí? –

+0

Sí, puedes. Ver mi respuesta –

+0

@David: Sí, eso también funciona. ¡Te sugiero que reemplaces tu respuesta que no funciona más arriba con ese comentario que funciona perfectamente! –

4

Un poco desordenada, pero se puede establecer la región de ventana poniendo esto en YourForm.OnShow evento:

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); 
+0

+1 Esto parece funcionar bien. –

+0

Por supuesto que sí.;-) – GolezTrol

+0

Esto tiene algunas limitaciones para la ventana principal de una aplicación. Consideraría que esta es una buena solución para un cuadro emergente, pero no para una ventana principal de la aplicación. –

-4

Necesita anular TForm.CreateParams y establecer o eliminar cualquier estilo que le interese

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

-1. Todos ya sabíamos * eso * mucho. –

+0

Estableciendo lo obvio aquí un poco. – Reallyethical

Cuestiones relacionadas