Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Zeichnen in Non-Client-Area unter Vista (https://www.delphipraxis.net/125128-zeichnen-non-client-area-unter-vista.html)

MasterEvil 1. Dez 2008 08:42


Zeichnen in Non-Client-Area unter Vista
 
Hallo,

ich habe eine abgeleitete DbGrid Komponente, die in den Non-Client Bereich einen Rahmen zeichnet.
Dies funktioniert unter WinXP wunderbar, unter Vista gibt es allerdings den Fehler "Leinwand/Bild erlaubt keine Zeichen".

Nach einer Google-Suche über spärliche Ergebnisse kam die Aussage, dass man unter Vista nicht mehr einfach in den Non-Client Bereich zeichnen darf. Man muss mittels der neuen API-Funktion DwmSetWindowAttribute das Property DWMWA_NCRENDERING_POLICY setzen, dann soll das wieder gehen.

Leider gibt es in Delphi 2007 scheinbar noch keinen Wrapper für diese Funktion. Auch habe ich keine Erklärung gefunden weshalb dies in Vista so geändert wurde. Oder bin ich hier allgemein auf dem Holzweg?

Für jeden Hinweis bin ich dankbar.
Gruß,
Steffen

turboPASCAL 1. Dez 2008 10:39

Re: Zeichnen in Non-Client-Area unter Vista
 
Du kannst auch die Desktopgestaltung deaktivieren. Dann sollte es keine Probleme geben.

Kannst du oder möchtest du dies nicht solltest du dir die DWM Funktionen mal ansehen.
Weitere Infos hier: zB.: http://msdn.microsoft.com/en-us/library/aa969530(VS.85).aspx


bzw. hier: http://msdn.microsoft.com/en-us/library/aa969524(VS.85).aspx

Die Umsetzung nach Delphi sähe dann ggf. so aus:

Delphi-Quellcode:
 // ... Siehe weiter unten ! ... //
Allerdings bekomme ich eine ExternalException. :gruebel:

Luckie 1. Dez 2008 12:15

Re: Zeichnen in Non-Client-Area unter Vista
 
Der genannte Fehler taucht auch dann auf, wenn man aus einem Thread mit der VCL interagiert ohne die Zugriffe zu synchronisieren. Einfachstes Beispiel man ruft in einem Thread ShowMesage auf, nimmt man eine API MessageBox geht es.

turboPASCAL 1. Dez 2008 12:19

Re: Zeichnen in Non-Client-Area unter Vista
 
Entschuldige, das verstehe ich jetzt nicht. Was soll ich synchronisieren ?

DGL-luke 1. Dez 2008 12:29

Re: Zeichnen in Non-Client-Area unter Vista
 
Luckie hat den Verdacht, dass du ein Synchronisierungsproblem haben könntest, weil External Exception-Fehler auch bei eben diesen auftreten.

turboPASCAL 1. Dez 2008 12:41

Re: Zeichnen in Non-Client-Area unter Vista
 
Liste der Anhänge anzeigen (Anzahl: 1)
Glaube ich eigentlich* nicht. :gruebel:

*ich wüsste dicht das man da etwas syncron. müsste.


Es kann aber auch an der Umsetzung des Quelltextes von C nach Delphi liegen...


Delphi-Quellcode:
implementation

{$R *.dfm}

// DWMFLIP3DWINDOWPOLICY
const
    DWMFLIP3D_DEFAULT     = 0;
    DWMFLIP3D_EXCLUDEBELOW = 1;
    DWMFLIP3D_EXCLUDEABOVE = 2;

type
  DWMFLIP3DWINDOWPOLICY = DWMFLIP3D_DEFAULT..DWMFLIP3D_EXCLUDEABOVE;


// DWMNCRENDERINGPOLICY
const
  DWMNCRP_USEWINDOWSTYLE = 0;
  DWMNCRP_DISABLED       = 1;
  DWMNCRP_ENABLED        = 2;
  DWMNCRP_LAST           = 3;

type
  TDWMNCRENDERINGPOLICY = DWMNCRP_USEWINDOWSTYLE..DWMNCRP_LAST;
  PDWMNCRENDERINGPOLICY = ^TDWMNCRENDERINGPOLICY;


// DWMWINDOWATTRIBUTE
const
  DWMWA_NCRENDERING_ENABLED      = 1;
  DWMWA_NCRENDERING_POLICY       = 2;
  DWMWA_TRANSITIONS_FORCEDISABLED = 3;
  DWMWA_ALLOW_NCPAINT            = 4;
  DWMWA_CAPTION_BUTTON_BOUNDS    = 5;
  DWMWA_NONCLIENT_RTL_LAYOUT     = 6;
  DWMWA_FORCE_ICONIC_REPRESENTATION = 7;
  DWMWA_FLIP3D_POLICY            = 8;
  DWMWA_EXTENDED_FRAME_BOUNDS    = 9;
  DWMWA_LAST                     = 10;

type
  TDWMWINDOWATTRIBUTE = DWMWA_NCRENDERING_ENABLED..DWMWA_LAST;


var
  hDWMDLL: THAndle;

  DwmSetWindowAttribute: function(WindowHandle: HWND; dwAttribute: DWORD;
    pvAttribute: Pointer; cbAttribute: DWORD): HRESULT; stdcall;


function DisableNCRendering(WindowHandle: HWND): BOOL;
var
  hr: HRESULT;
  ncrp: TDWMNCRENDERINGPOLICY;
begin
  Result := FALSE;
  if @DwmSetWindowAttribute <> nil then
  begin
    ncrp := DWMNCRP_ENABLED;

    //disable non-client area rendering on window
    hr := DwmSetWindowAttribute(WindowHandle, DWMWA_NCRENDERING_POLICY, @ncrp, sizeof(ncrp));

    Result := Bool( hr = S_OK );
  end;
end;

function DisableFlip3D(WindowHandle: HWND): BOOL;
var
  hr: HRESULT;
  flip: TDWMNCRENDERINGPOLICY;
begin
  Result := FALSE;
  if @DwmSetWindowAttribute <> nil then
  begin
    flip := DWMFLIP3D_EXCLUDEBELOW;

    //disable non-client area rendering on window
    hr := DwmSetWindowAttribute(WindowHandle, DWMWA_FLIP3D_POLICY, @flip, sizeof(flip));

    Result := Bool( hr = S_OK );
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  hDWMDLL := LoadLibrary('DWMAPI.DLL');
  if hDWMDLL <> 0 then
  begin
    @DwmSetWindowAttribute := GetProcAddress(hDWMDLL, 'DwmSetWindowAttribute');
    if not DisableNCRendering(Self.Handle) // das FormX.Handle
      then ShowMessage('DwmSetWindowAttribute konnte ggf. das Attribut nicht setzen.');

    // oder: DisableFlip3D(Self.Handle);
  end;

  if hDWMDLL <> 0 then FreeLibrary(hDWMDLL);
end;

end.

turboPASCAL 1. Dez 2008 15:50

Re: Zeichnen in Non-Client-Area unter Vista
 
bei

Delphi-Quellcode:
var
  DwmSetWindowAttribute: function(WindowHandle: HWND; dwAttribute: DWORD;
    pvAttribute: Pointer {LPCVOID}; cbAttribute: DWORD): HRESULT;
fehlt das stdcall; dann kommt auch keine AV mehr. ;)

also:

Delphi-Quellcode:
var
  DwmSetWindowAttribute: function(WindowHandle: HWND; dwAttribute: DWORD;
    pvAttribute: Pointer {LPCVOID}; cbAttribute: DWORD): HRESULT; stdcall;

MasterEvil 1. Dez 2008 16:28

Re: Zeichnen in Non-Client-Area unter Vista
 
Hallo,

erstmal vielen Dank! Das hat mir schon sehr geholfen.
Leider setzt er die NCR-Policy bei mir nicht um :(
Das Result ist immer false.
Bei mir sieht das so aus:
Delphi-Quellcode:
function SetNCRendering(WindowHandle: HWND; Enable: Boolean): Boolean;
var
  Hr             : HRESULT;
  Policy         : TDWMNCRENDERINGPOLICY;
begin
  Result:=true;
  if WinIsVista then
  begin
    Result:=false;
    hDWMDLL:=LoadLibrary('DWMAPI.DLL');
    if hDWMDLL<>0 then
    begin
      @DwmSetWindowAttribute:=GetProcAddress(hDWMDLL,'DwmSetWindowAttribute');
      if @DwmSetWindowAttribute<>nil then
      begin
        if Enable then Policy:=DWMNCRP_ENABLED
        else Policy:=DWMNCRP_DISABLED;
        Hr:=DwmSetWindowAttribute(WindowHandle,DWMWA_NCRENDERING_POLICY,@Policy,SizeOf(Policy));
        Result:=Hr=S_OK;
      end;

      FreeLibrary(hDWMDLL);
    end;
  end;
end;
Ich muss es ja vorallem aktivieren, damit ich eben in die NC Area zeichnen kann.
Er ruft die Routine auch auf, aber Hr ist leider nicht S_OK.
Eine Idee?

Gruß,
Steffen

turboPASCAL 1. Dez 2008 16:56

Re: Zeichnen in Non-Client-Area unter Vista
 
Quellcode oben aktualisiert.


Das ist was mich auch wundert, eigentlich ist alles so wie MS es gern hätte. :gruebel:

Das selbe Problem habe ich auch mit dem Flip3D-Zeugs. HRESULT ist immer <> S_OK also False.


Man könne blöde werden.

MasterEvil 2. Dez 2008 07:33

Re: Zeichnen in Non-Client-Area unter Vista
 
Also geht es auch bei dir nicht?
Mhhh ... muss doch irgendwie gehen ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:12 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz