AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Zeichnen in Non-Client-Area unter Vista

Zeichnen in Non-Client-Area unter Vista

Ein Thema von MasterEvil · begonnen am 1. Dez 2008 · letzter Beitrag vom 25. Sep 2018
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von MasterEvil
MasterEvil

Registriert seit: 12. Feb 2005
Ort: Hannover
234 Beiträge
 
Delphi 7 Enterprise
 
#1

Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 09:42
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
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#2

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 11:39
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:

 // ... Siehe weiter unten ! ... // Allerdings bekomme ich eine ExternalException.
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie
(Moderator)

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 13:15
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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#4

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 13:19
Entschuldige, das verstehe ich jetzt nicht. Was soll ich synchronisieren ?
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 13:29
Luckie hat den Verdacht, dass du ein Synchronisierungsproblem haben könntest, weil External Exception-Fehler auch bei eben diesen auftreten.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#6

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 13:41
Glaube ich eigentlich* nicht.

*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.
Angehängte Dateien
Dateityp: zip dwmsetwindowattributetest_195.zip (217,7 KB, 37x aufgerufen)
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#7

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 16:50
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;
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von MasterEvil
MasterEvil

Registriert seit: 12. Feb 2005
Ort: Hannover
234 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 17:28
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
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#9

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 1. Dez 2008, 17:56
Quellcode oben aktualisiert.


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

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


Man könne blöde werden.
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Benutzerbild von MasterEvil
MasterEvil

Registriert seit: 12. Feb 2005
Ort: Hannover
234 Beiträge
 
Delphi 7 Enterprise
 
#10

Re: Zeichnen in Non-Client-Area unter Vista

  Alt 2. Dez 2008, 08:33
Also geht es auch bei dir nicht?
Mhhh ... muss doch irgendwie gehen ...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf