Jump to content


Photo

[MULTILENGUAJE] Ventana desplegable translúcida, una alternativa a AnimateWindow


  • Please log in to reply
28 replies to this topic

#21 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4483 posts
  • LocationVenezuela

Posted 23 November 2010 - 09:52 AM

No se si a alguien mas le sucede, pero me da un problemita, a la tercera o cuarta vez que aparece a lo que se quita el mensaje me muestra unos caracteres especiales, adjunto la imagen.

Quise solucionar pero la verdad es que no entiendo mucho el codigo.

Attached Files


  • 0

#22 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 23 November 2010 - 11:59 AM

No consigo reproducir el error  ^o|

Subo una aplicación de ejemplo con el código fuente y binario y me cuentas como te funciona.


Saludos.
  • 0

#23 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4483 posts
  • LocationVenezuela

Posted 24 November 2010 - 01:02 AM

Con este ultimo codigo si funciona, muchas gracias.

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.
  • 0

#24 seoane

seoane

    Advanced Member

  • Administrador
  • 1259 posts
  • LocationEspaña

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:


delphi
  1. hFrame:= CreateWindowEx(WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE, 'UPMSG', '',WS_POPUP
  2.                           ,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:


delphi
  1. const WS_EX_NOACTIVATE = $8000000;


  • 0

#25 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4483 posts
  • LocationVenezuela

Posted 24 November 2010 - 02:47 AM

Ok ahora si funciona, la aplicación que lo lanza si pierde el foco, pero lo lanzo desde una aplicacion secundaria y se resuelve el problema.

Muchas gracias
  • 0

#26 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

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.
  • 0

#27 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 24 November 2010 - 11:09 AM

Para los que no terminen de entender el código decir que usa sólo la API de Win32. Se basa en crear una ventana simple y asignarle una función de tratamiento de mensajes.

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:

delphi
  1.   hPrev:= GetFocus;
  2.   hFrame:= CreateWindowEx(WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW, 'UPMSG', '',WS_VISIBLE or WS_POPUP
  3.                           ,X, Y, W, 0, HWND_DESKTOP, HMENU(0), hInstance, nil);
  4.   SetLayeredWindowAttributes(hFrame, 0, 200, LWA_ALPHA);
  5.   SetTimer(hFrame, 0, 20, @OnTimer);
  6.   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.
  • 0

#28 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4483 posts
  • LocationVenezuela

Posted 24 November 2010 - 12:10 PM

Simplemente excelente gracias.
Ya imprimi la documentacion de setwimdowes para revisarlo con calma
  • 0

#29 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

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:


delphi
  1. unit TBUMessage;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows, Classes, SysUtils;
  9.  
  10.  
  11. procedure TaskBarUpMessage(cMsg: string; cX, cY, cW, cH, cMargin, cTime: integer; cColor: COLORREF);
  12.  
  13.  
  14. implementation
  15.  
  16. var
  17.   YMax: integer = 0;
  18.   X: integer = 0;
  19.   Y: integer = 0;
  20.   W: integer = 0;
  21.   H: integer = 0;
  22.   Msg: PCHAR = nil;
  23.   Color: COLORREF = 0;
  24.   Time: integer = 0;
  25.   hInstance: LongWord = 0;
  26.   Margin: integer = 0;
  27.   Wait: Pointer = nil;
  28.  
  29.  
  30. procedure OnTimer(hWnd: THandle; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;
  31. const
  32.   Inc: integer = 2;
  33. var
  34.   Rect: TRect;
  35.   DC: HDC;
  36.   Brush: HBRUSH;
  37. begin
  38.   if idEvent <> 0 then exit;
  39.   if (YMax-Y > H) and (Inc>0)then
  40.   begin
  41.     Inc:= -Inc;
  42.     KillTimer(hWnd, 0);
  43.     SetTimer(hWnd, 1, Time, TIMERPROC(Wait));
  44.   end;
  45.   if (YMax<=Y) and(Inc<0) then
  46.   begin
  47.     Inc:= -Inc;
  48.     SendMessage(hWnd, WM_CLOSE, 0, 0);
  49.     Windows.UnregisterClass('UPMSG', hInstance);
  50.     exit;
  51.   end;
  52.   Y:= Y-Inc;
  53.   MoveWindow(hWnd, X, Y, W, YMax-Y, false);
  54. end;
  55.  
  56. procedure OnWait(hWnd: THandle; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;
  57. begin
  58.   if idEvent = 1 then
  59.   begin
  60.     KillTimer(hWnd, 1);
  61.     SetTimer(hWnd, 0, 5, TIMERPROC(@OnTimer));
  62.   end;
  63. end;
  64.  
  65. function WindowProc(hWnd: THandle; uMsg, wParam, lParam: integer): LRESULT; stdcall;
  66. var
  67.   DC: HDC;
  68.   Rect: TRect;
  69.   Brush: HBRUSH;
  70.  
  71. begin
  72.   if uMsg = WM_PAINT then
  73.   begin
  74.     DC:= GetWindowDC(hWnd);
  75.     Rect.Left:= Margin; Rect.Top:= Margin; Rect.Right:= W; Rect.Bottom:= H;
  76.     Brush:= CreateSolidBrush(Color);
  77.     SelectObject(DC, Brush);
  78.     Rectangle(DC, 0, 0, W, H);
  79.     SetTextColor(DC, RGB(0,0,0));
  80.     SetBkColor(DC, Color);
  81.     DrawText(DC, Msg, lstrlen(Msg), Rect, DT_LEFT);
  82.     DeleteObject(Brush);
  83.     ReleaseDC(hWnd, DC);
  84.   end;
  85.   Result:= DefWindowProc(hWnd, uMsg, wParam, lParam);
  86. end;
  87.  
  88.  
  89. procedure TaskBarUpMessage(cMsg: string; cX, cY, cW, cH, cMargin, cTime: integer; cColor: COLORREF);
  90. var
  91.   RectArea: TRect;
  92.   Size: TSize;
  93.   CharSize: TSize;
  94.   DC: HDC;
  95.   WinClass: WNDCLASS;
  96.   hFrame, hPrev: THandle;
  97.  
  98.   procedure GetTextExtentML(DC: HDC; Msg: PCHAR; Len: integer; var Size: TSize);
  99.   var
  100.     Ancho, Alto, nLines: integer;
  101.     C, Ini: PCHAR;
  102.   begin
  103.     Ancho:= 0; Alto:= 0; nLines:= 0;
  104.     Ancho:= 0; Alto:= 0; nLines:= 0;
  105.     C:= Msg; Ini:= Msg;
  106.     repeat
  107.       if ((C+1)^ = #13) or ((C+1)^ = #0) then
  108.       begin
  109.         GetTextExtentPoint32(DC, Ini, DWORD(C)-DWORD(Ini)+1, Size);
  110.         if Ancho < Size.cx then Ancho:= Size.cx;
  111.         if Alto  < Size.cy then Alto:=  Size.cy;
  112.         Ini:= C;
  113.         inc(nLines);
  114.       end;
  115.       inc(C);
  116.     until C^ = #0;
  117.     Size.cx:= Ancho;
  118.     Size.cy:= Alto*nLines;
  119.   end;
  120.  
  121. begin
  122.   Wait:= @OnWait;
  123.   SystemParametersInfo(SPI_GETWORKAREA, 0, @RectArea, 0);
  124.   Msg:= PCHAR(cMsg);
  125.   YMax:= RectArea.bottom;
  126.   X:= cX;
  127.   Y:= cY;
  128.   W:= cW;
  129.   H:= cH;
  130.   Color:= cColor;
  131.   Time:= cTime;
  132.   DC:= GetDC(0);
  133.   GetTextExtentML(DC, PCHAR(Msg), Length(Msg), Size);
  134.  
  135.   GetTextExtentPoint32(DC, 'H', 1, CharSize);
  136.   if Margin = 0 then Margin:= CharSize.cy;
  137.   if W = 0 then W:= Size.cx + Margin*2;
  138.   if H = 0 then H:= Size.cy + Margin*2;
  139.   if X = 0 then X:= RectArea.right - W - Margin;;
  140.   if (Y<>0) and (Y<YMax-H) then YMax:= H+Y;
  141.  
  142.   Y:= YMax;
  143.   ReleaseDC(0, DC);
  144.   with WinClass do
  145.   begin
  146.     style:= 0;
  147.     lpfnWndProc:= WNDPROC(@WindowProc);
  148.     cbClsExtra:= 0;
  149.     cbWndExtra:= 0;
  150.     hInstance:= 0;
  151.     hIcon:= 0;
  152.     hCursor:= 0;
  153.     hbrBackground:= 0;
  154.     lpszMenuName:= '';
  155.     lpszClassName:= 'UPMSG';
  156.   end;
  157.   Windows.RegisterClass(WinClass);
  158.   hPrev:= GetFocus;
  159.   hFrame:= CreateWindowEx(WS_EX_LAYERED or WS_EX_TOPMOST or WS_EX_TOOLWINDOW, 'UPMSG', '',WS_VISIBLE or WS_POPUP
  160.                           ,X, Y, W, 0, HWND_DESKTOP, HMENU(0), hInstance, nil);
  161.   SetLayeredWindowAttributes(hFrame, 0, 200, LWA_ALPHA);
  162.   SetTimer(hFrame, 0, 20, @OnTimer);
  163.   SetFocus(hPrev);
  164. end;
  165.  
  166.  
  167. end.


Un Ejemplo de uso:


delphi
  1. 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.
  • 1




IP.Board spam blocked by CleanTalk.