Einzelnen Beitrag anzeigen

sebastianz1983

Registriert seit: 26. Jan 2010
Ort: Regensburg
14 Beiträge
 
#18

Re: Größenverhältnis der Form bei Größenänderung beibehalten

  Alt 29. Jan 2010, 07:51
Zitat von hoika:
Hallo,

Zitat:
weil in einem bestehenden Projekt hier in der Arbeit jetzt alle Fenster und deren Controls bei Größenänderung mitskalieren solle
Schon mal an Formular-Vererbung gedacht ?


Heiko
Für die Vererbung muss ich doch wieder alle Formulare anfassen, oder etwa nicht? Geh mal bitte davon aus, dass ich die nicht verändern will und wohl auch nicht darf.

Hab noch ein bisschen rumgespielt und hab jetzt zusätzlich eine Ereignisbehandlung für WM_SIZE eingebaut, die via SendMessage() eine weitere WM_SIZE Nachricht (mit der von mir gewollten Größe des Fensters) wirft.

Hier mal der aktuell von mir abgeänderte Code:

Delphi-Quellcode:
unit TestSizeHook;

interface

procedure StartProportionalSizing; stdcall; forward;
procedure StopProportionalSizing; stdcall; forward;

implementation
uses Windows, Forms, Dialogs, Messages, SysUtils, Math, Classes, Controls,
  Types;

var
  glbSizeHook: cardinal = 0;
  glbRatio: single;
  glbHookRunning: boolean = FALSE;
  glbWindowRect: TRect;

function Hook(code: Integer; W: wParam; L: lParam): LResult; stdcall;
type
  pCWPStruct = ^CWPSTRUCT;

var
  currentCWP: CWPSTRUCT;
  windowRect: TRect;
  PWindowRect: PRect;
  newSize: integer;

begin
  if (code >= HC_ACTION) then begin
    currentCWP := pCWPStruct(L)^;

    case currentCWP.message of
      WM_ENTERSIZEMOVE: begin
        if GetWindowRect(currentCWP.hwnd, windowRect) then
          glbRatio := (windowRect.Right - windowRect.Left) / (windowRect.Bottom - windowRect.Top);
      end;

      WM_SIZING: begin
        if not glbHookRunning then begin
          PWindowRect := PRect(currentCWP.LParam);
          glbWindowRect := PWindowRect^;
          case currentCWP.WParam of
            WMSZ_BOTTOM, WMSZ_TOP,
            WMSZ_TOPLEFT, WMSZ_TOPRIGHT, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT: begin
              newSize := trunc(SimpleRoundTo((PWindowRect.Bottom - PWindowRect.Top + 1) * glbRatio, 0));
              PWindowRect.Right := PWindowRect.Left + newSize;
            end;

            WMSZ_LEFT, WMSZ_RIGHT: begin
              newSize := trunc(SimpleRoundTo((PWindowRect.Right - PWindowRect.Left + 1) / glbRatio, 0));
              PWindowRect.Bottom := PWindowRect.Top + newSize;
            end;
          end;
          MoveWindow(currentCWP.hwnd,
                     PWindowRect.Left,
                     PWindowRect.Top,
                     PWindowRect.Right - PWindowRect.Left,
                     PWindowRect.Bottom - PWindowRect.Top,
                     TRUE);
          glbHookRunning := TRUE;
        end;
      end;

      WM_SIZE: begin
        if not glbHookRunning then begin
          newSize := WORD(glbWindowRect.Bottom - glbWindowRect.Top) shl (SizeOf(WORD) * 8) + WORD(glbWindowRect.Right - glbWindowRect.Left);
          SendMessage(currentCWP.hwnd, WM_SIZE, w, newSize);
          glbHookRunning := TRUE;
        end;
      end;
    end;
    glbHookRunning := FALSE;
  end;

  result := CallNextHookEx(glbSizeHook, code, w, l);
end;

procedure StartProportionalSizing;
begin
  if glbSizeHook = 0 then
    glbSizeHook := SetWindowsHookEx(WH_CALLWNDPROC, @Hook, 0, GetCurrentThreadID());
end;

procedure StopProportionalSizing;
begin
  if glbSizeHook <> 0 then
    UnhookWindowsHookEx(glbSizeHook);
end;

end.
Ergebnis hierbei:
Das Flackern wird geringer. Da sowohl in der WM_SIZING als auch in der WM_SIZE die korrekte Größe des Fensters gesetzt wird. Das ist allerdings auch noch nicht das Gelbe vom Ei, weil am Ende wohl doch nochmal ein WM_SIZE von Windows abgearbeitet wird, das die Größe wieder auf die ursprüngliche setzt.

Aus meiner Sicht fehlt mir nur noch das Abfangen (und Verwerfen) dieses letzten WM_SIZE Ereignisses, das das Fenster wieder auf die Standardgröße zurücksetzt.

Werden wirklich ALLE Ereignisse eines Threads an einen Threadhook geschickt? Und kann ich dieses Ereignis abhandeln, ohne dass dies an den normalen Handler weitergereicht wird? Dann müsste ich doch auch dieses Ereignis einfach stoppen können, oder nicht?


Sebastian
  Mit Zitat antworten Zitat