PDA

Ver la Versión Completa : Desplegar por código el menú de sistema de una ventana


Jan_polero
05-05-2005, 16:21:34
Hola a todos. En una aplicación utilizo paneles como barras de título de las ventanas, poniéndole yo los botones y toda la pesca. Mi problema es que no sé cómo hacer que se despliege el menú de sistema de la ventana (ese que aparece cuando pulsas sobre el icono de una ventana de Windows) al pulsar uno de los botones. Espero podais ayudarme. Gracias por adelantado y un saludo.

Neftali [Germán.Estévez]
05-05-2005, 17:17:51
Programar en cualquier componente de pantalla que se desee que responda al click el siguiente código en el
evento MouseDown.


procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
h: HMENU;
p:TPoint;
begin

// El componente que llama deriva de TControl?
if (Sender is TControl) then begin
// POsicion del click
p.X := x;
p.Y := y;
// Calculamos las coordenadas relativas
P := Self.ScreenToClient(TControl(Sender).ClientToScreen(P));

// Mostrar el menú
h := GetSystemMenu(handle, false);
TrackPopupMenu(h, TPM_LEFTALIGN or TPM_LEFTBUTTON,
ClientOrigin.X + p.X ,
ClientOrigin.Y + p.y, 0, handle, nil);
end;
end;

roman
05-05-2005, 17:19:29
El siguiente código te desplegará el menú en la esquina superior izquierda de un botón:


var
Pt: TPoint;

begin
Pt := Point(Button1.Left, Button1.Top);
Pt := ClientToScreen(Pt);

SendMessage(Handle, $0313, 0, LParam(PointToSmallPoint(Pt)));
end;


// Saludos

roman
05-05-2005, 17:21:45
La solución de Neftalí fue la primera que pensé pero, al menos en mi caso, aunque sí muestra el menú, no responde a los comandos.

// Saludos

Neftali [Germán.Estévez]
05-05-2005, 18:24:42
al menos en mi caso, aunque sí muestra el menú, no responde a los comandos. Cierto en mi caso tampoco... ?¿?¿? Curioso, no me había dado cuenta.
Revisando la API TrackPopupMenu dice lo siguiente:

hWnd
Identifies the window that owns the shortcut menu. This window receives all messages from the menu. The window does not receive a WM_COMMAND message from the menu until the function returns.

y ésto:
Remarks
Accelerator keystrokes that select items from the window menu are translated into WM_SYSCOMMAND messages.


Por lo tanto si el Handle que se le pasa como parámetro recibe el mensaje, se supone que se puede capturar ese mensaje y enviarlo a la cola de mensajes para que se procese.

Define en la parte privada el método:


procedure WMCommand(var msg: TWMCommand); message WM_COMMAND;
...

// Y su implementacion...

procedure TForm1.WMCommand(var msg: TWMCommand);
begin
PostMessage(handle, WM_SYSCOMMAND, TMessage(msg).WParam, TMessage(msg).LParam);
inherited;
end;


Funciona, pero la cosa se va complicando... La solución de Román como mínimo es más corta y funciona igual de bien.

roman
05-05-2005, 18:32:15
Funciona, pero la cosa se va complicando


Je, je. Ya había llegado a esa conclusión. La otra solución no es mía sino que la acabo de ver buscando en los foros de Borland. Lo que sí es que parece ser que el mensaje $0313 no está documentado en el SDK de Windows.

// Saludos

Jan_polero
06-05-2005, 09:39:33
Gracias, funciona perfectamente. Por cierto, una última cosa: cómo puedo minimizar mi aplicación en la barra de tareas? (actualmente se minimiza en la parte inferior izquierda de la pantalla, usando el WindowState del form). Un saludo.

S.M.S.
06-05-2005, 12:35:25
Prueba con:
Application.Minimize;

Saludos.