Quise solucionar pero la verdad es que no entiendo mucho el codigo.
[MULTILENGUAJE] Ventana desplegable translúcida, una alternativa a AnimateWindow
#21
Posted 23 November 2010 - 09:52 AM
Quise solucionar pero la verdad es que no entiendo mucho el codigo.
#22
Posted 23 November 2010 - 11:59 AM
Subo una aplicación de ejemplo con el código fuente y binario y me cuentas como te funciona.
Saludos.
#23
Posted 24 November 2010 - 01:02 AM
Ahora una pregunta mas, hay posibilidad de ejecutarlo en segundo plano? es decir que cuando salga la ventana no pierda el foco la aplicación activa.
#24
Posted 24 November 2010 - 02:28 AM
Ahora una pregunta mas, hay posibilidad de ejecutarlo en segundo plano? es decir que cuando salga la ventana no pierda el foco la aplicación activa.
Prueba con esto:
hFrame:= CreateWindowEx(WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE, 'UPMSG', '',WS_POPUP ,X, Y, W, H, HWND_DESKTOP, HMENU(0), hInstance, nil);
Si no tienes declarada la constante WS_EX_NOACTIVATE en tu versión de delphi:
const WS_EX_NOACTIVATE = $8000000;
#25
Posted 24 November 2010 - 02:47 AM
Muchas gracias
#26
Posted 24 November 2010 - 02:58 AM
Con este ultimo codigo si funciona, muchas gracias.
No recuerdo haber cambiado nada en el código, tal como lo escribí y probé lo publiqué, si bien es verdad que no lo he contrastado linea a línea con el que guardo yo.
Cuando tenga un rato tranquilo con mis compiladores miraré que se puede hacer con el tama del foco.
Un detalle que no he comentado pero que me parece obbio es que la ventana se puede mostrar en cualquier lugar del escritorio, no sólo encima del SysTray...
Saludos.
#27
Posted 24 November 2010 - 11:09 AM
Los mensajes que va a tratar son W_PAINT que se encargará de pintar un rectángulo de un color y colocar un texto.
Dos timer, uno para mover la ventana en sentido ascendente y descendente. El otro Timer sirve para controlar el tiempo de espera cuando la ventada esté desplegada por completo.
Decir que para poder realizarlo con submétodos me he visto obligado a usar constantes a las que fuerzo para poder cambiar su valor con la directiva {$J+}. En C++ estas variables se denominan static y no son constantes, aunque no pierden su valor entre llamadas.
He resuelto el tema de la pérdida del foco de la aplicación que llama a TaskBarUpMessage. La solución es simple voy a tratar de explicarla.
En primer lugar debemos tomar el foco de la ventana que lo tiene antes de crear nuestra ventana popup, ese foco estará en la ventana que llama a TaskBarUpMessage, es decir una ventana de la aplicación.
En segundo lugar, el movimiento de la ventana popup debe realizarse con la API MoveWindow en lugar de SetWindowPos, pues esta última pone el foco en la ventana que manipula.
Para que lo anterior funcione, debemos definir la ventana popup como visible (WS_VISIBLE) pero de altura 0 al inicio, para que no se vea.
Por último creamos la ventana y tras esto devolvemos el foco a la ventana que previamdente lo tenía, así parece que la ventana que llama a TaskBarUpMessage nunca perdió el foco.
Esta es la fracción de código que crea la ventana popup y devuelve el foco a su dueño original:
hPrev:= GetFocus; hFrame:= CreateWindowEx(WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW, 'UPMSG', '',WS_VISIBLE or WS_POPUP ,X, Y, W, 0, HWND_DESKTOP, HMENU(0), hInstance, nil); SetLayeredWindowAttributes(hFrame, 0, 200, LWA_ALPHA); SetTimer(hFrame, 0, 20, @OnTimer); SetFocus(hPrev);
He cambiado el código en los apartados correspondientes en C++ y delphi a la par que subo en una aplicación de ejemplo para ambos casos PopUp_C++.rar y PopUp_delphi.rar
Con vuestras sugerencias, necesidades y dudas se va completando.
Saludos.
#28
Posted 24 November 2010 - 12:10 PM
Ya imprimi la documentacion de setwimdowes para revisarlo con calma
#29
Posted 03 July 2012 - 04:01 AM
Resucito el tema para añadir una adaptación del código para Lazarus. La idea surge de este otro hilo a instancias de enecumene.
En esta ocasión escribo una Unit:
unit TBUMessage; {$mode objfpc}{$H+} interface uses Windows, Classes, SysUtils; procedure TaskBarUpMessage(cMsg: string; cX, cY, cW, cH, cMargin, cTime: integer; cColor: COLORREF); implementation var YMax: integer = 0; X: integer = 0; Y: integer = 0; W: integer = 0; H: integer = 0; Msg: PCHAR = nil; Color: COLORREF = 0; Time: integer = 0; hInstance: LongWord = 0; Margin: integer = 0; Wait: Pointer = nil; procedure OnTimer(hWnd: THandle; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall; const Inc: integer = 2; var Rect: TRect; DC: HDC; Brush: HBRUSH; begin if idEvent <> 0 then exit; if (YMax-Y > H) and (Inc>0)then begin Inc:= -Inc; KillTimer(hWnd, 0); SetTimer(hWnd, 1, Time, TIMERPROC(Wait)); end; if (YMax<=Y) and(Inc<0) then begin Inc:= -Inc; SendMessage(hWnd, WM_CLOSE, 0, 0); Windows.UnregisterClass('UPMSG', hInstance); exit; end; Y:= Y-Inc; MoveWindow(hWnd, X, Y, W, YMax-Y, false); end; procedure OnWait(hWnd: THandle; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall; begin if idEvent = 1 then begin KillTimer(hWnd, 1); SetTimer(hWnd, 0, 5, TIMERPROC(@OnTimer)); end; end; function WindowProc(hWnd: THandle; uMsg, wParam, lParam: integer): LRESULT; stdcall; var DC: HDC; Rect: TRect; Brush: HBRUSH; begin if uMsg = WM_PAINT then begin DC:= GetWindowDC(hWnd); Rect.Left:= Margin; Rect.Top:= Margin; Rect.Right:= W; Rect.Bottom:= H; Brush:= CreateSolidBrush(Color); SelectObject(DC, Brush); Rectangle(DC, 0, 0, W, H); SetTextColor(DC, RGB(0,0,0)); SetBkColor(DC, Color); DrawText(DC, Msg, lstrlen(Msg), Rect, DT_LEFT); DeleteObject(Brush); ReleaseDC(hWnd, DC); end; Result:= DefWindowProc(hWnd, uMsg, wParam, lParam); end; procedure TaskBarUpMessage(cMsg: string; cX, cY, cW, cH, cMargin, cTime: integer; cColor: COLORREF); var RectArea: TRect; Size: TSize; CharSize: TSize; DC: HDC; WinClass: WNDCLASS; hFrame, hPrev: THandle; procedure GetTextExtentML(DC: HDC; Msg: PCHAR; Len: integer; var Size: TSize); var Ancho, Alto, nLines: integer; C, Ini: PCHAR; begin Ancho:= 0; Alto:= 0; nLines:= 0; Ancho:= 0; Alto:= 0; nLines:= 0; C:= Msg; Ini:= Msg; repeat if ((C+1)^ = #13) or ((C+1)^ = #0) then begin GetTextExtentPoint32(DC, Ini, DWORD(C)-DWORD(Ini)+1, Size); if Ancho < Size.cx then Ancho:= Size.cx; if Alto < Size.cy then Alto:= Size.cy; Ini:= C; inc(nLines); end; inc(C); until C^ = #0; Size.cx:= Ancho; Size.cy:= Alto*nLines; end; begin Wait:= @OnWait; SystemParametersInfo(SPI_GETWORKAREA, 0, @RectArea, 0); Msg:= PCHAR(cMsg); YMax:= RectArea.bottom; X:= cX; Y:= cY; W:= cW; H:= cH; Color:= cColor; Time:= cTime; DC:= GetDC(0); GetTextExtentML(DC, PCHAR(Msg), Length(Msg), Size); GetTextExtentPoint32(DC, 'H', 1, CharSize); if Margin = 0 then Margin:= CharSize.cy; if W = 0 then W:= Size.cx + Margin*2; if H = 0 then H:= Size.cy + Margin*2; if X = 0 then X:= RectArea.right - W - Margin;; if (Y<>0) and (Y<YMax-H) then YMax:= H+Y; Y:= YMax; ReleaseDC(0, DC); with WinClass do begin style:= 0; lpfnWndProc:= WNDPROC(@WindowProc); cbClsExtra:= 0; cbWndExtra:= 0; hInstance:= 0; hIcon:= 0; hCursor:= 0; hbrBackground:= 0; lpszMenuName:= ''; lpszClassName:= 'UPMSG'; end; Windows.RegisterClass(WinClass); hPrev:= GetFocus; hFrame:= CreateWindowEx(WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW, 'UPMSG', '',WS_VISIBLE or WS_POPUP ,X, Y, W, 0, HWND_DESKTOP, HMENU(0), hInstance, nil); SetLayeredWindowAttributes(hFrame, 0, 200, LWA_ALPHA); SetTimer(hFrame, 0, 20, @OnTimer); SetFocus(hPrev); end; end.
Un Ejemplo de uso:
TaskBarUpMessage('Esta es la versi'+#243+'n para'+#13+'Lazarus.'+#13+'Que la disfruten.', 0, 0, 0, 0, 0, 2000, clRed);
Subo un ejemplo.
Saludos.
Edito para solucionar error en las etiquetas de código.