Toon posts:

[Delphi] Monitor desktop changes

Pagina: 1
Acties:

Verwijderd

Topicstarter
Dit is geen vraag, maar een antwoord op de vraag van MisterE in [topic=460128].
yep, maar prob. is eigenlijk dat ik wil 'intercepten' wanneer de iconen veranderd worden.
ik ben namelijk een wallpaper manager aan het maken, en ik wil er voor zorgen dat de iconen de goede kleur blijven behouden.
Mijn code is eigenlijk opgefleurde code van gajits; Note dat de opmerkingen mbt Set8087CW, niet meer gelden voor Delphi 5 en later.

In het kort komt het erop neer dat je in een dll een library-defined hook maakt, die kijkt welke messages er naar alle windows worden gestuurd.

Ergens heb ik het gevoel dat deze code een beetje overkill is, dus als je wat beters weet, hoor ik het graag.

Dll Code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
library Capture;

uses
  SysUtils,
  Classes,
  Windows,
  CommCtrl,
  Messages;

{$R *.RES}

type
  PHookRec = ^THookRec;
  THookRec = record
    MainWindow: THandle;
    SysView32: THandle;
    HookID: HHOOK;
  end;

const
  CM_IconTextChanged = WM_USER + 1;

const
  HookRecPtr: PHookRec = nil;
  MappingHandle: THandle = 0;

procedure SetMainHandle(Handle: HWnd);
begin
  HookRecPtr.MainWindow := Handle;
end;

procedure SetSysView32(Handle: HWnd);
begin
  HookRecPtr.SysView32 := Handle;
end;

function HookProc(Code: Integer; WParam: Longint; var Msg: TCWPStruct): Longint;
  stdcall;
begin
  { We monitoren alleen messsages die naar de desktop SysView32
    worden gestuurd }
  if (Msg.HWnd = HookRecPtr.SysView32) then
    case Msg.Message of
    
    { Hier kunnen meerdere messages, die je 
      wilt monitoren, toegevoegd worden }
    LVM_SETTEXTCOLOR, LVM_SETTEXTBKCOLOR:
      PostMessage(HookRecPtr.MainWindow, CM_IconTextChanged, Msg.Message, 0);
    end;
  Result := CallNextHookEx(HookRecPtr.HookID, Code, WParam, Longint(@Msg))
end;

procedure SetHook;
begin
  HookRecPtr.HookID := SetWindowsHookEx(WH_CALLWNDPROC, @HookProc, HInstance,
    0);
end;

procedure UnSetHook;
begin
  UnHookWindowsHookEx(HookRecPtr.HookID);
end;

exports
  SetHook,
  UnSetHook,
  SetMainHandle,
  SetSysView32;

procedure EntryPointProc(Reason: Integer);
begin
  case reason of
    DLL_PROCESS_ATTACH:
    begin
      MappingHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
        SizeOf(THookRec), 'CaptureDesktopEvents');
      HookRecPtr := MapViewOfFile(MappingHandle, FILE_MAP_WRITE, 0, 0, 0);
    end;
    DLL_PROCESS_DETACH:
    begin
      try
        if HookRecPtr <> nil then
        UnMapViewOfFile(HookRecPtr);
        if MappingHandle <> 0 then
        CloseHandle(MappingHandle);
      except
      end;
    end;
  end;
end;

begin
  DllProc := @EntryPointProc;
  EntryPointProc(DLL_PROCESS_ATTACH);
end.

Applicatie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
unit Capture02;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

{ Beetje lelijk om 2x dezelfde constante te definieren }
const
  CM_IconTextChanged = WM_USER + 1;

type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  protected
    procedure CMIconTextChanged(var Message: TMessage); message
    CM_IconTextChanged;
  end;

var
  Form2: TForm2;

implementation

uses
  CommCtrl;

{$R *.DFM}

procedure SetHook; external 'capture.dll';
procedure UnSetHook; external 'capture.dll';
procedure SetMainHandle(Handle: HWnd); external 'capture.dll';
procedure SetSysView32(Handle: HWnd); external 'capture.dll';

function GetSysView32: THandle;
var
  ProgMan, Shell: THandle;
begin
  ProgMan := FindWindowEx(GetDesktopWindow, 0, 'ProgMan', nil);
  Shell := FindWindowEx(ProgMan, 0, 'SHELLDLL_DefView', nil);
  Result := FindWindowEx(Shell, 0, 'SysListView32', nil);
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  SetSysView32(GetSysView32);
  SetMainHandle(Handle);
  SetHook;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  UnSetHook;
end;

procedure TForm2.CMIconTextChanged(var Message: TMessage);
begin
  case Message.WParam of
    LVM_SETTEXTCOLOR:
    ListBox1.Items.Add('LVM_SETTEXTCOLOR');
    LVM_SETTEXTBKCOLOR:
    ListBox1.Items.Add('LVM_SETTEXTBKCOLOR');
  else
    ListBox1.Items.Add('Unknown');
  end;
end;

end.