~ubuntu-branches/ubuntu/saucy/lazarus/saucy

« back to all changes in this revision

Viewing changes to lcl/interfaces/customdrawn/customdrawn_winproc.pas

  • Committer: Package Import Robot
  • Author(s): Paul Gevers, Abou Al Montacir, Bart Martens, Paul Gevers
  • Date: 2013-06-08 14:12:17 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20130608141217-7k0cy9id8ifcnutc
Tags: 1.0.8+dfsg-1
[ Abou Al Montacir ]
* New upstream major release and multiple maintenace release offering many
  fixes and new features marking a new milestone for the Lazarus development
  and its stability level.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_fixes_branch
* LCL changes:
  - LCL is now a normal package.
      + Platform independent parts of the LCL are now in the package LCLBase
      + LCL is automatically recompiled when switching the target platform,
        unless pre-compiled binaries for this target are already installed.
      + No impact on existing projects.
      + Linker options needed by LCL are no more added to projects that do
        not use the LCL package.
  - Minor changes in LCL basic classes behaviour
      + TCustomForm.Create raises an exception if a form resource is not
        found.
      + TNotebook and TPage: a new implementation of these classes was added.
      + TDBNavigator: It is now possible to have focusable buttons by setting
        Options = [navFocusableButtons] and TabStop = True, useful for
        accessibility and for devices with neither mouse nor touch screen.
      + Names of TControlBorderSpacing.GetSideSpace and GetSpace were swapped
        and are now consistent. GetSideSpace = Around + GetSpace.
      + TForm.WindowState=wsFullscreen was added
      + TCanvas.TextFitInfo was added to calculate how many characters will
        fit into a specified Width. Useful for word-wrapping calculations.
      + TControl.GetColorResolvingParent and
        TControl.GetRGBColorResolvingParent were added, simplifying the work
        to obtain the final color of the control while resolving clDefault
        and the ParentColor.
      + LCLIntf.GetTextExtentExPoint now has a good default implementation
        which works in any platform not providing a specific implementation.
        However, Widgetset specific implementation is better, when available.
      + TTabControl was reorganized. Now it has the correct class hierarchy
        and inherits from TCustomTabControl as it should.
  - New unit in the LCL:
      + lazdialogs.pas: adds non-native versions of various native dialogs,
        for example TLazOpenDialog, TLazSaveDialog, TLazSelectDirectoryDialog.
        It is used by widgetsets which either do not have a native dialog, or
        do not wish to use it because it is limited. These dialogs can also be
        used by user applications directly.
      + lazdeviceapis.pas: offers an interface to more hardware devices such
        as the accelerometer, GPS, etc. See LazDeviceAPIs
      + lazcanvas.pas: provides a TFPImageCanvas descendent implementing
        drawing in a LCL-compatible way, but 100% in Pascal.
      + lazregions.pas. LazRegions is a wholly Pascal implementation of
        regions for canvas clipping, event clipping, finding in which control
        of a region tree one an event should reach, for drawing polygons, etc.
      + customdrawncontrols.pas, customdrawndrawers.pas,
        customdrawn_common.pas, customdrawn_android.pas and
        customdrawn_winxp.pas: are the Lazarus Custom Drawn Controls -controls
        which imitate the standard LCL ones, but with the difference that they
        are non-native and support skinning.
  - New APIs added to the LCL to improve support of accessibility software
    such as screen readers.
* IDE changes:
  - Many improvments.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/New_IDE_features_since#v1.0_.282012-08-29.29
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes#IDE_Changes
* Debugger / Editor changes:
  - Added pascal sources and breakpoints to the disassembler
  - Added threads dialog.
* Components changes:
  - TAChart: many fixes and new features
  - CodeTool: support Delphi style generics and new syntax extensions.
  - AggPas: removed to honor free licencing. (Closes: Bug#708695)
[Bart Martens]
* New debian/watch file fixing issues with upstream RC release.
[Abou Al Montacir]
* Avoid changing files in .pc hidden directory, these are used by quilt for
  internal purpose and could lead to surprises during build.
[Paul Gevers]
* Updated get-orig-source target and it compinion script orig-tar.sh so that they
  repack the source file, allowing bug 708695 to be fixed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{                        ------------------------------
 
2
                               winproc.pp
 
3
                         ------------------------------
 
4
 
 
5
 Misc types and procedures for LCL-CustomDrawn-Windows
 
6
 
 
7
 *****************************************************************************
 
8
 *                                                                           *
 
9
 *  This file is part of the Lazarus Component Library (LCL)                 *
 
10
 *                                                                           *
 
11
 *  See the file COPYING.modifiedLGPL.txt, included in this distribution,    *
 
12
 *  for details about the copyright.                                         *
 
13
 *                                                                           *
 
14
 *  This program is distributed in the hope that it will be useful,          *
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
 
17
 *                                                                           *
 
18
 *****************************************************************************
 
19
}
 
20
 
 
21
unit customdrawn_winproc;
 
22
 
 
23
{$mode objfpc}{$H+}
 
24
 
 
25
interface
 
26
 
 
27
uses
 
28
  Windows, CTypes, Classes, SysUtils,
 
29
  // LCL
 
30
  LCLType, Interfacebase, LMessages, lclintf, LCLMessageGlue, LCLProc,
 
31
  Controls, Forms, graphtype, Menus, IntfGraphics, lazcanvas,
 
32
  //
 
33
  customdrawnproc;
 
34
 
 
35
type
 
36
  MCHITTESTINFO = record
 
37
    cbSize: UINT;
 
38
    pt    : TPoint;
 
39
    uHit  : UINT;          // out param
 
40
    st    : SYSTEMTIME;
 
41
  end;
 
42
  TMCMHitTestInfo = MCHITTESTINFO;
 
43
  PMCMHitTestInfo = ^TMCMHitTestInfo;
 
44
 
 
45
  // Window information snapshot
 
46
  tagWINDOWINFO = record
 
47
    cbSize: DWORD;
 
48
    rcWindow: TRect;
 
49
    rcClient: TRect;
 
50
    dwStyle: DWORD;
 
51
    dwExStyle: DWORD;
 
52
    dwWindowStatus: DWORD;
 
53
    cxWindowBorders: UINT;
 
54
    cyWindowBorders: UINT;
 
55
    atomWindowType: ATOM;
 
56
    wCreatorVersion: WORD;
 
57
  end;
 
58
  PTAGWINDOWINFO = ^tagWINDOWINFO;
 
59
 
 
60
type
 
61
  { lazarus win32 Interface definition for additional timer data needed to find the callback}
 
62
  PWinCETimerInfo = ^TWinCETimerinfo;
 
63
  TWinCETimerInfo = record
 
64
    TimerID: UINT_PTR;         // the windows timer ID for this timer
 
65
    TimerFunc: TWSTimerProc; // owner function to handle timer
 
66
  end;
 
67
 
 
68
{$ifdef WinCE}
 
69
function EnumDisplayMonitors(hdc: HDC; lprcClip: PRect; lpfnEnum: MONITORENUMPROC; dwData: LPARAM): LongBool; cdecl; external KernelDLL name 'EnumDisplayMonitors';
 
70
function GetMonitorInfoW(hMonitor: HMONITOR; lpmi: PMonitorInfo): LongBool; cdecl; external KernelDLL name 'GetMonitorInfo';
 
71
function MonitorFromWindow(hWnd: HWND; dwFlags: DWORD): HMONITOR; cdecl; external KernelDLL name 'MonitorFromWindow';
 
72
function MonitorFromRect(lprcScreenCoords: PRect; dwFlags: DWord): HMONITOR; cdecl; external KernelDLL name 'MonitorFromRect';
 
73
function MonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWord): HMONITOR; cdecl; external KernelDLL name 'MonitorFromPoint';
 
74
{$else}
 
75
function EnumDisplayMonitors(hdc: HDC; lprcClip: PRect; lpfnEnum: MONITORENUMPROC; dwData: LPARAM): LongBool; stdcall; external 'user32.dll' name 'EnumDisplayMonitors';
 
76
function GetMonitorInfoW(hMonitor: HMONITOR; lpmi: PMonitorInfo): LongBool; stdcall; external 'user32.dll' name 'GetMonitorInfoW';
 
77
function MonitorFromWindow(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall; external 'user32.dll' name 'MonitorFromWindow';
 
78
function MonitorFromRect(lprcScreenCoords: PRect; dwFlags: DWord): HMONITOR; stdcall; external 'user32.dll' name 'MonitorFromRect';
 
79
function MonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWord): HMONITOR; stdcall; external 'user32.dll' name 'MonitorFromPoint';
 
80
// from win32extra.pp
 
81
function GetWindowInfo(hwnd: HWND; pwi: PTAGWINDOWINFO): BOOL; stdcall; external 'user32.dll' name 'GetWindowInfo';
 
82
{$endif}
 
83
 
 
84
type
 
85
  TMouseDownFocusStatus = (mfNone, mfFocusSense, mfFocusChanged);
 
86
 
 
87
  PProcessEvent = ^TProcessEvent;
 
88
  TProcessEvent = record
 
89
    Handle: THandle;
 
90
    Handler: PEventHandler;
 
91
    UserData: PtrInt;
 
92
    OnEvent: TChildExitEvent;
 
93
  end;
 
94
 
 
95
var
 
96
  // FTimerData contains the currently running timers
 
97
  FTimerData : TList;   // list of PWin32Timerinfo
 
98
 
 
99
  MouseDownTime: dword;
 
100
  MouseDownPos: TPoint;
 
101
  MouseDownWindow: HWND = 0;
 
102
  MouseDownFocusWindow: HWND;
 
103
  MouseDownFocusStatus: TMouseDownFocusStatus = mfNone;
 
104
  ComboBoxHandleSizeWindow: HWND = 0;//just do not know the use yet
 
105
  IgnoreNextCharWindow: HWND = 0;  // ignore next WM_(SYS)CHAR message
 
106
  OnClipBoardRequest: TClipboardRequestEvent = nil;
 
107
 
 
108
type
 
109
  TEventType = (etNotify, etKey, etKeyPress, etMouseWheel, etMouseUpDown);
 
110
 
 
111
  TWindowInfo = class(TCDForm)
 
112
    Overlay: HWND;            // overlay, transparent window on top, used by designer
 
113
    //PopupMenu: TPopupMenu;
 
114
    DefWndProc: WNDPROC;
 
115
    ParentPanel: HWND;        // if non-zero, is the tabsheet window, for the pagecontrol hack
 
116
    List: TStrings;
 
117
    StayOnTopList: TList;     // a list of windows that were normalized when showing modal
 
118
    MaxLength: dword;
 
119
    MouseX, MouseY: word; // noticing spurious WM_MOUSEMOVE messages
 
120
    // CD additions
 
121
    Bitmap: HBITMAP;
 
122
    BitmapWidth: integer;
 
123
    BitmapHeight: integer;
 
124
    BitmapDC, DCBitmapOld: HDC;
 
125
  end;
 
126
 
 
127
  PStayOnTopWindowsInfo = ^TStayOnTopWindowsInfo;
 
128
  TStayOnTopWindowsInfo = record
 
129
    AppHandle: HWND;
 
130
    SystemTopAlso: Boolean;
 
131
    StayOnTopList: TList;
 
132
  end;
 
133
 
 
134
  TWindowsVersion = (
 
135
    wvUnknown,
 
136
    //
 
137
    wince_1,
 
138
    wince_2,
 
139
    wince_3,
 
140
    wince_4,
 
141
    wince_5,
 
142
    wince_6,
 
143
    wince_6_1,
 
144
    wince_6_5,
 
145
    wince_7,
 
146
    wince_other,
 
147
    //
 
148
    wv95,
 
149
    wvNT4,
 
150
    wv98,
 
151
    wvMe,
 
152
    wv2000,
 
153
    wvXP,
 
154
    wvServer2003,
 
155
    //wvServer2003R2,  // has the same major/minor as wvServer2003
 
156
    wvVista,
 
157
    //wvServer2008,    // has the same major/minor as wvVista
 
158
    wv7,
 
159
    wv8,
 
160
    wvLater
 
161
  );
 
162
 
 
163
function WM_To_String(WM_Message: Integer): string;
 
164
function WindowPosFlagsToString(Flags: UINT): string;
 
165
function ObjectToHWND(Const AObject: TObject): HWND;
 
166
 
 
167
function BytesPerLine(nWidth, nBitsPerPixel: Integer): PtrUInt;
 
168
function CreateDIBSectionFromDescription(ADC: HDC; const ADesc: TRawImageDescription; out ABitsPtr: Pointer): HBITMAP;
 
169
procedure FillRawImageDescriptionColors(var ADesc: TRawImageDescription);
 
170
procedure FillRawImageDescription(const ABitmapInfo: Windows.TBitmap; out ADesc: TRawImageDescription);
 
171
function WinProc_RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean;
 
172
function WinProc_RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean;
 
173
 
 
174
{$ifndef WinCE}
 
175
function GetBitmapOrder(AWinBmp: Windows.TBitmap; ABitmap: HBITMAP):TRawImageLineOrder;
 
176
{$endif}
 
177
function GetBitmapBytes(AWinBmp: Windows.TBitmap; ABitmap: HBITMAP; const ARect: TRect; ALineEnd: TRawImageLineEnd; ALineOrder: TRawImageLineOrder; out AData: Pointer; out ADataSize: PtrUInt): Boolean;
 
178
function IsAlphaBitmap(ABitmap: HBITMAP): Boolean;
 
179
function IsAlphaDC(ADC: HDC): Boolean;
 
180
 
 
181
function GetLastErrorText(AErrorCode: Cardinal): WideString;
 
182
 
 
183
function LCLControlSizeNeedsUpdate(Sender: TWinControl;
 
184
  SendSizeMsgOnDiff: boolean): boolean;
 
185
 
 
186
function GetLCLClientBoundsOffset(Sender: TObject; var ORect: TRect): boolean;
 
187
function GetLCLClientBoundsOffset(Handle: TWindowInfo; var Rect: TRect): boolean;
 
188
procedure LCLBoundsToWin32Bounds(Sender: TObject;
 
189
  var Left, Top, Width, Height: Integer);
 
190
procedure LCLFormSizeToWin32Size(Form: TCustomForm; var AWidth, AHeight: Integer);
 
191
procedure GetWin32ControlPos(Window, Parent: HWND; var Left, Top: integer);
 
192
 
 
193
function GetWindowInfo(AWindow: HWND): TWindowInfo;
 
194
 
 
195
procedure UpdateWindowStyle(Handle: HWnd; Style: integer; StyleMask: integer);
 
196
function BorderStyleToWinAPIFlags(Style: TFormBorderStyle): DWORD;
 
197
function BorderStyleToWinAPIFlagsEx(AForm: TCustomForm; Style: TFormBorderStyle): DWORD;
 
198
 
 
199
function GetFileVersion(FileName: string): dword;
 
200
 
 
201
procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False);
 
202
procedure RestoreStayOnTopFlags(AppHandle: HWND);
 
203
 
 
204
procedure AddToChangedMenus(Window: HWnd);
 
205
procedure RedrawMenus;
 
206
function MeasureText(const AWinControl: TWinControl; Text: string; var Width, Height: integer): boolean;
 
207
function GetControlText(AHandle: HWND): string;
 
208
 
 
209
{ String functions that may be moved to the RTL in the future }
 
210
procedure WideStrCopy(Dest, Src: PWideChar);
 
211
function WideStrLCopy(dest, source: PWideChar; maxlen: SizeInt): PWideChar;
 
212
function WideStrCmp(W1, W2: PWideChar): Integer;
 
213
 
 
214
{ Automatic detection of platform }
 
215
function GetWinCEPlatform: TApplicationType;
 
216
function IsHiResMode: Boolean;
 
217
procedure UpdateWindowsVersion;
 
218
 
 
219
var
 
220
  DefaultWindowInfo: TWindowInfo;
 
221
  WindowInfoAtom: ATOM;
 
222
  OverwriteCheck: Integer = 0;
 
223
  ChangedMenus: TList; // list of HWNDs which menus needs to be redrawn
 
224
 
 
225
  WindowsVersion: TWindowsVersion = wvUnknown;
 
226
 
 
227
const
 
228
  ClsName: array[0..6] of WideChar = ('W', 'i', 'n', 'd', 'o', 'w', #0);
 
229
  ClsHintName: array[0..10] of WideChar = ('H', 'i', 'n', 't', 'W', 'i', 'n', 'd', 'o', 'w', #0);
 
230
 
 
231
implementation
 
232
 
 
233
uses customdrawnint;
 
234
 
 
235
var
 
236
  InRemoveStayOnTopFlags: Integer = 0;
 
237
 
 
238
{------------------------------------------------------------------------------
 
239
  Function: WM_To_String
 
240
  Params: WM_Message - a WinDows message
 
241
  Returns: A WinDows-message name
 
242
 
 
243
  Converts a winDows message identIfier to a string
 
244
 ------------------------------------------------------------------------------}
 
245
function WM_To_String(WM_Message: Integer): string;
 
246
Begin
 
247
 Case WM_Message of
 
248
  $0000: Result := 'WM_NULL';
 
249
  $0001: Result := 'WM_CREATE';
 
250
  $0002: Result := 'WM_DESTROY';
 
251
  $0003: Result := 'WM_MOVE';
 
252
  $0005: Result := 'WM_SIZE';
 
253
  $0006: Result := 'WM_ACTIVATE';
 
254
  $0007: Result := 'WM_SETFOCUS';
 
255
  $0008: Result := 'WM_KILLFOCUS';
 
256
  $000A: Result := 'WM_ENABLE';
 
257
  $000B: Result := 'WM_SETREDRAW';
 
258
  $000C: Result := 'WM_SETTEXT';
 
259
  $000D: Result := 'WM_GETTEXT';
 
260
  $000E: Result := 'WM_GETTEXTLENGTH';
 
261
  $000F: Result := 'WM_PAINT';
 
262
  $0010: Result := 'WM_CLOSE';
 
263
  $0011: Result := 'WM_QUERYENDSESSION';
 
264
  $0012: Result := 'WM_QUIT';
 
265
  $0013: Result := 'WM_QUERYOPEN';
 
266
  $0014: Result := 'WM_ERASEBKGND';
 
267
  $0015: Result := 'WM_SYSCOLORCHANGE';
 
268
  $0016: Result := 'WM_EndSESSION';
 
269
  $0017: Result := 'WM_SYSTEMERROR';
 
270
  $0018: Result := 'WM_SHOWWINDOW';
 
271
  $0019: Result := 'WM_CTLCOLOR';
 
272
  $001A: Result := 'WM_WININICHANGE or WM_SETTINGCHANGE';
 
273
  $001B: Result := 'WM_DEVMODECHANGE';
 
274
  $001C: Result := 'WM_ACTIVATEAPP';
 
275
  $001D: Result := 'WM_FONTCHANGE';
 
276
  $001E: Result := 'WM_TIMECHANGE';
 
277
  $001F: Result := 'WM_CANCELMODE';
 
278
  $0020: Result := 'WM_SETCURSOR';
 
279
  $0021: Result := 'WM_MOUSEACTIVATE';
 
280
  $0022: Result := 'WM_CHILDACTIVATE';
 
281
  $0023: Result := 'WM_QUEUESYNC';
 
282
  $0024: Result := 'WM_GETMINMAXINFO';
 
283
  $0026: Result := 'WM_PAINTICON';
 
284
  $0027: Result := 'WM_ICONERASEBKGND';
 
285
  $0028: Result := 'WM_NEXTDLGCTL';
 
286
  $002A: Result := 'WM_SPOOLERSTATUS';
 
287
  $002B: Result := 'WM_DRAWITEM';
 
288
  $002C: Result := 'WM_MEASUREITEM';
 
289
  $002D: Result := 'WM_DELETEITEM';
 
290
  $002E: Result := 'WM_VKEYTOITEM';
 
291
  $002F: Result := 'WM_CHARTOITEM';
 
292
  $0030: Result := 'WM_SETFONT';
 
293
  $0031: Result := 'WM_GETFONT';
 
294
  $0032: Result := 'WM_SETHOTKEY';
 
295
  $0033: Result := 'WM_GETHOTKEY';
 
296
  $0037: Result := 'WM_QUERYDRAGICON';
 
297
  $0039: Result := 'WM_COMPAREITEM';
 
298
  $003D: Result := 'WM_GETOBJECT';
 
299
  $0041: Result := 'WM_COMPACTING';
 
300
  $0044: Result := 'WM_COMMNOTIFY { obsolete in Win32}';
 
301
  $0046: Result := 'WM_WINDOWPOSCHANGING';
 
302
  $0047: Result := 'WM_WINDOWPOSCHANGED';
 
303
  $0048: Result := 'WM_POWER';
 
304
  $004A: Result := 'WM_COPYDATA';
 
305
  $004B: Result := 'WM_CANCELJOURNAL';
 
306
  $004E: Result := 'WM_NOTIFY';
 
307
  $0050: Result := 'WM_INPUTLANGCHANGEREQUEST';
 
308
  $0051: Result := 'WM_INPUTLANGCHANGE';
 
309
  $0052: Result := 'WM_TCARD';
 
310
  $0053: Result := 'WM_HELP';
 
311
  $0054: Result := 'WM_USERCHANGED';
 
312
  $0055: Result := 'WM_NOTIFYFORMAT';
 
313
  $007B: Result := 'WM_CONTEXTMENU';
 
314
  $007C: Result := 'WM_STYLECHANGING';
 
315
  $007D: Result := 'WM_STYLECHANGED';
 
316
  $007E: Result := 'WM_DISPLAYCHANGE';
 
317
  $007F: Result := 'WM_GETICON';
 
318
  $0080: Result := 'WM_SETICON';
 
319
  $0081: Result := 'WM_NCCREATE';
 
320
  $0082: Result := 'WM_NCDESTROY';
 
321
  $0083: Result := 'WM_NCCALCSIZE';
 
322
  $0084: Result := 'WM_NCHITTEST';
 
323
  $0085: Result := 'WM_NCPAINT';
 
324
  $0086: Result := 'WM_NCACTIVATE';
 
325
  $0087: Result := 'WM_GETDLGCODE';
 
326
  $00A0: Result := 'WM_NCMOUSEMOVE';
 
327
  $00A1: Result := 'WM_NCLBUTTONDOWN';
 
328
  $00A2: Result := 'WM_NCLBUTTONUP';
 
329
  $00A3: Result := 'WM_NCLBUTTONDBLCLK';
 
330
  $00A4: Result := 'WM_NCRBUTTONDOWN';
 
331
  $00A5: Result := 'WM_NCRBUTTONUP';
 
332
  $00A6: Result := 'WM_NCRBUTTONDBLCLK';
 
333
  $00A7: Result := 'WM_NCMBUTTONDOWN';
 
334
  $00A8: Result := 'WM_NCMBUTTONUP';
 
335
  $00A9: Result := 'WM_NCMBUTTONDBLCLK';
 
336
  $0100: Result := 'WM_KEYFIRST or WM_KEYDOWN';
 
337
  $0101: Result := 'WM_KEYUP';
 
338
  $0102: Result := 'WM_CHAR';
 
339
  $0103: Result := 'WM_DEADCHAR';
 
340
  $0104: Result := 'WM_SYSKEYDOWN';
 
341
  $0105: Result := 'WM_SYSKEYUP';
 
342
  $0106: Result := 'WM_SYSCHAR';
 
343
  $0107: Result := 'WM_SYSDEADCHAR';
 
344
  $0108: Result := 'WM_KEYLAST';
 
345
  $010D: Result := 'WM_IME_STARTCOMPOSITION';
 
346
  $010E: Result := 'WM_IME_ENDCOMPOSITION';
 
347
  $010F: Result := 'WM_IME_COMPOSITION or WM_IME_KEYLAST';
 
348
  $0110: Result := 'WM_INITDIALOG';
 
349
  $0111: Result := 'WM_COMMAND';
 
350
  $0112: Result := 'WM_SYSCOMMAND';
 
351
  $0113: Result := 'WM_TIMER';
 
352
  $0114: Result := 'WM_HSCROLL';
 
353
  $0115: Result := 'WM_VSCROLL';
 
354
  $0116: Result := 'WM_INITMENU';
 
355
  $0117: Result := 'WM_INITMENUPOPUP';
 
356
  $011F: Result := 'WM_MENUSELECT';
 
357
  $0120: Result := 'WM_MENUCHAR';
 
358
  $0121: Result := 'WM_ENTERIDLE';
 
359
  $0122: Result := 'WM_MENURBUTTONUP';
 
360
  $0123: Result := 'WM_MENUDRAG';
 
361
  $0124: Result := 'WM_MENUGETOBJECT';
 
362
  $0125: Result := 'WM_UNINITMENUPOPUP';
 
363
  $0126: Result := 'WM_MENUCOMMAND';
 
364
  $0132: Result := 'WM_CTLCOLORMSGBOX';
 
365
  $0133: Result := 'WM_CTLCOLOREDIT';
 
366
  $0134: Result := 'WM_CTLCOLORLISTBOX';
 
367
  $0135: Result := 'WM_CTLCOLORBTN';
 
368
  $0136: Result := 'WM_CTLCOLORDLG';
 
369
  $0137: Result := 'WM_CTLCOLORSCROLLBAR';
 
370
  $0138: Result := 'WM_CTLCOLORSTATIC';
 
371
  $0200: Result := 'WM_MOUSEFIRST or WM_MOUSEMOVE';
 
372
  $0201: Result := 'WM_LBUTTONDOWN';
 
373
  $0202: Result := 'WM_LBUTTONUP';
 
374
  $0203: Result := 'WM_LBUTTONDBLCLK';
 
375
  $0204: Result := 'WM_RBUTTONDOWN';
 
376
  $0205: Result := 'WM_RBUTTONUP';
 
377
  $0206: Result := 'WM_RBUTTONDBLCLK';
 
378
  $0207: Result := 'WM_MBUTTONDOWN';
 
379
  $0208: Result := 'WM_MBUTTONUP';
 
380
  $0209: Result := 'WM_MBUTTONDBLCLK';
 
381
  $020A: Result := 'WM_MOUSEWHEEL or WM_MOUSELAST';
 
382
  $0210: Result := 'WM_PARENTNOTIFY';
 
383
  $0211: Result := 'WM_ENTERMENULOOP';
 
384
  $0212: Result := 'WM_EXITMENULOOP';
 
385
  $0213: Result := 'WM_NEXTMENU';
 
386
  $0214: Result := 'WM_SIZING';
 
387
  $0215: Result := 'WM_CAPTURECHANGED';
 
388
  $0216: Result := 'WM_MOVING';
 
389
  $0218: Result := 'WM_POWERBROADCAST';
 
390
  $0219: Result := 'WM_DEVICECHANGE';
 
391
  $0220: Result := 'WM_MDICREATE';
 
392
  $0221: Result := 'WM_MDIDESTROY';
 
393
  $0222: Result := 'WM_MDIACTIVATE';
 
394
  $0223: Result := 'WM_MDIRESTORE';
 
395
  $0224: Result := 'WM_MDINEXT';
 
396
  $0225: Result := 'WM_MDIMAXIMIZE';
 
397
  $0226: Result := 'WM_MDITILE';
 
398
  $0227: Result := 'WM_MDICASCADE';
 
399
  $0228: Result := 'WM_MDIICONARRANGE';
 
400
  $0229: Result := 'WM_MDIGETACTIVE';
 
401
  $0230: Result := 'WM_MDISETMENU';
 
402
  $0231: Result := 'WM_ENTERSIZEMOVE';
 
403
  $0232: Result := 'WM_EXITSIZEMOVE';
 
404
  $0233: Result := 'WM_DROPFILES';
 
405
  $0234: Result := 'WM_MDIREFRESHMENU';
 
406
  $0281: Result := 'WM_IME_SETCONTEXT';
 
407
  $0282: Result := 'WM_IME_NOTIFY';
 
408
  $0283: Result := 'WM_IME_CONTROL';
 
409
  $0284: Result := 'WM_IME_COMPOSITIONFULL';
 
410
  $0285: Result := 'WM_IME_SELECT';
 
411
  $0286: Result := 'WM_IME_CHAR';
 
412
  $0288: Result := 'WM_IME_REQUEST';
 
413
  $0290: Result := 'WM_IME_KEYDOWN';
 
414
  $0291: Result := 'WM_IME_KEYUP';
 
415
  $02A1: Result := 'WM_MOUSEHOVER';
 
416
  $02A3: Result := 'WM_MOUSELEAVE';
 
417
  $0300: Result := 'WM_CUT';
 
418
  $0301: Result := 'WM_COPY';
 
419
  $0302: Result := 'WM_PASTE';
 
420
  $0303: Result := 'WM_CLEAR';
 
421
  $0304: Result := 'WM_UNDO';
 
422
  $0305: Result := 'WM_RENDERFORMAT';
 
423
  $0306: Result := 'WM_RENDERALLFORMATS';
 
424
  $0307: Result := 'WM_DESTROYCLIPBOARD';
 
425
  $0308: Result := 'WM_DRAWCLIPBOARD';
 
426
  $0309: Result := 'WM_PAINTCLIPBOARD';
 
427
  $030A: Result := 'WM_VSCROLLCLIPBOARD';
 
428
  $030B: Result := 'WM_SIZECLIPBOARD';
 
429
  $030C: Result := 'WM_ASKCBFORMATNAME';
 
430
  $030D: Result := 'WM_CHANGECBCHAIN';
 
431
  $030E: Result := 'WM_HSCROLLCLIPBOARD';
 
432
  $030F: Result := 'WM_QUERYNEWPALETTE';
 
433
  $0310: Result := 'WM_PALETTEISCHANGING';
 
434
  $0311: Result := 'WM_PALETTECHANGED';
 
435
  $0312: Result := 'WM_HOTKEY';
 
436
  $0317: Result := 'WM_PRINT';
 
437
  $0318: Result := 'WM_PRINTCLIENT';
 
438
  $0358: Result := 'WM_HANDHELDFIRST';
 
439
  $035F: Result := 'WM_HANDHELDLAST';
 
440
  $0380: Result := 'WM_PENWINFIRST';
 
441
  $038F: Result := 'WM_PENWINLAST';
 
442
  $0390: Result := 'WM_COALESCE_FIRST';
 
443
  $039F: Result := 'WM_COALESCE_LAST';
 
444
  $03E0: Result := 'WM_DDE_FIRST or WM_DDE_INITIATE';
 
445
  $03E1: Result := 'WM_DDE_TERMINATE';
 
446
  $03E2: Result := 'WM_DDE_ADVISE';
 
447
  $03E3: Result := 'WM_DDE_UNADVISE';
 
448
  $03E4: Result := 'WM_DDE_ACK';
 
449
  $03E5: Result := 'WM_DDE_DATA';
 
450
  $03E6: Result := 'WM_DDE_REQUEST';
 
451
  $03E7: Result := 'WM_DDE_POKE';
 
452
  $03E8: Result := 'WM_DDE_EXECUTE or WM_DDE_LAST';
 
453
  $0400: Result := 'WM_USER';
 
454
  $8000: Result := 'WM_APP';
 
455
  Else
 
456
    Result := 'Unknown(' + IntToStr(WM_Message) + ')';
 
457
  End; {Case}
 
458
End;
 
459
 
 
460
function WindowPosFlagsToString(Flags: UINT): string;
 
461
var
 
462
  FlagsStr: string;
 
463
begin
 
464
  FlagsStr := '';
 
465
  if (Flags and SWP_DRAWFRAME) <> 0 then
 
466
    FlagsStr := FlagsStr + '|SWP_DRAWFRAME';
 
467
  if (Flags and SWP_HIDEWINDOW) <> 0 then
 
468
    FlagsStr := FlagsStr + '|SWP_HIDEWINDOW';
 
469
  if (Flags and SWP_NOACTIVATE) <> 0 then
 
470
    FlagsStr := FlagsStr + '|SWP_NOACTIVATE';
 
471
  if (Flags and SWP_NOCOPYBITS) <> 0 then
 
472
    FlagsStr := FlagsStr + '|SWP_NOCOPYBITS';
 
473
  if (Flags and SWP_NOMOVE) <> 0 then
 
474
    FlagsStr := FlagsStr + '|SWP_NOMOVE';
 
475
  if (Flags and SWP_NOOWNERZORDER) <> 0 then
 
476
    FlagsStr := FlagsStr + '|SWP_NOOWNERZORDER';
 
477
  if (Flags and SWP_NOREDRAW) <> 0 then
 
478
    FlagsStr := FlagsStr + '|SWP_NOREDRAW';
 
479
  if (Flags and SWP_NOSENDCHANGING) <> 0 then
 
480
    FlagsStr := FlagsStr + '|SWP_NOSENDCHANGING';
 
481
  if (Flags and SWP_NOSIZE) <> 0 then
 
482
    FlagsStr := FlagsStr + '|SWP_NOSIZE';
 
483
  if (Flags and SWP_NOZORDER) <> 0 then
 
484
    FlagsStr := FlagsStr + '|SWP_NOZORDER';
 
485
  if (Flags and SWP_SHOWWINDOW) <> 0 then
 
486
    FlagsStr := FlagsStr + '|SWP_SHOWWINDOW';
 
487
  if Length(FlagsStr) > 0 then
 
488
    FlagsStr := Copy(FlagsStr, 2, Length(FlagsStr)-1);
 
489
  Result := FlagsStr;
 
490
end;
 
491
 
 
492
{------------------------------------------------------------------------------
 
493
  Procedure: GetWin32KeyInfo
 
494
  Params:  Event      - Requested info
 
495
           KeyCode    - the ASCII key code of the eventkey
 
496
           VirtualKey - the virtual key code of the eventkey
 
497
           SysKey     - True If the key is a syskey
 
498
           ExtEnded   - True If the key is an extended key
 
499
           Toggle     - True If the key is a toggle key and its value is on
 
500
  Returns: Nothing
 
501
 
 
502
  GetWin32KeyInfo returns information about the given key event
 
503
 ------------------------------------------------------------------------------}
 
504
{
 
505
procedure GetWin32KeyInfo(const Event: Integer; var KeyCode, VirtualKey: Integer; var SysKey, Extended, Toggle: Boolean);
 
506
Const
 
507
  MVK_UNIFY_SIDES = 1;
 
508
Begin
 
509
  //DebugLn('TRACE:Using function GetWin32KeyInfo which isn''t implemented yet');
 
510
  KeyCode := Word(Event);
 
511
  VirtualKey := MapVirtualKey(KeyCode, MVK_UNIFY_SIDES);
 
512
  SysKey := (VirtualKey = VK_SHIFT) Or (VirtualKey = VK_CONTROL) Or (VirtualKey = VK_MENU);
 
513
  ExtEnded := (SysKey) Or (VirtualKey = VK_INSERT) Or (VirtualKey = VK_HOME) Or (VirtualKey = VK_LEFT) Or (VirtualKey = VK_UP) Or (VirtualKey = VK_RIGHT) Or (VirtualKey = VK_DOWN) Or (VirtualKey = VK_PRIOR) Or (VirtualKey = VK_NEXT) Or (VirtualKey = VK_END) Or (VirtualKey = VK_DIVIDE);
 
514
  Toggle := Lo(GetKeyState(VirtualKey)) = 1;
 
515
End;
 
516
}
 
517
 
 
518
{------------------------------------------------------------------------------
 
519
  Function: ObjectToHWND
 
520
  Params: AObject - An LCL Object
 
521
  Returns: The Window handle of the given object
 
522
 
 
523
  Returns the Window handle of the given object, 0 if no object available
 
524
 ------------------------------------------------------------------------------}
 
525
function ObjectToHWND(Const AObject: TObject): HWND;
 
526
Var
 
527
  Handle: HWND;
 
528
Begin
 
529
  Handle:=0;
 
530
  If not assigned(AObject) Then
 
531
  Begin
 
532
    Assert (False, 'TRACE:[ObjectToHWND] Object not assigned');
 
533
  End
 
534
  Else If (AObject Is TWinControl) Then
 
535
  Begin
 
536
    If TWinControl(AObject).HandleAllocated Then
 
537
      Handle := TWinControl(AObject).Handle
 
538
  End
 
539
  Else If (AObject Is TMenuItem) Then
 
540
  Begin
 
541
    If TMenuItem(AObject).HandleAllocated Then
 
542
      Handle := TMenuItem(AObject).Handle
 
543
  End
 
544
  Else If (AObject Is TMenu) Then
 
545
  Begin
 
546
    If TMenu(AObject).HandleAllocated Then
 
547
      Handle := TMenu(AObject).Items.Handle
 
548
  End
 
549
//  Else If (AObject Is TCommonDialog) Then
 
550
//  Begin
 
551
//    {If TCommonDialog(AObject).HandleAllocated Then }
 
552
//    Handle := TCommonDialog(AObject).Handle
 
553
//  End
 
554
  Else
 
555
  Begin
 
556
    //DebugLn(Format('Trace:[ObjectToHWND] Message received With unhandled class-type <%s>', [AObject.ClassName]));
 
557
  End;
 
558
  Result := Handle;
 
559
  If Handle = 0 Then
 
560
    Assert (False, 'Trace:[ObjectToHWND]****** Warning: handle = 0 *******');
 
561
end;
 
562
 
 
563
function BytesPerLine(nWidth, nBitsPerPixel: Integer): PtrUInt;
 
564
begin
 
565
  Result := ((nWidth * nBitsPerPixel + 31) and (not 31) ) div 8;
 
566
end;
 
567
 
 
568
procedure FillRawImageDescriptionColors(var ADesc: TRawImageDescription);
 
569
begin
 
570
  case ADesc.BitsPerPixel of
 
571
    1,4,8:
 
572
      begin
 
573
        // palette mode, no offsets
 
574
        ADesc.Format := ricfGray;
 
575
        ADesc.RedPrec := ADesc.BitsPerPixel;
 
576
        ADesc.GreenPrec := 0;
 
577
        ADesc.BluePrec := 0;
 
578
        ADesc.RedShift := 0;
 
579
        ADesc.GreenShift := 0;
 
580
        ADesc.BlueShift := 0;
 
581
      end;
 
582
    16:
 
583
      begin
 
584
        // 5-6-5 mode
 
585
        //roozbeh all changed from 5-5-5 to 5-6-5
 
586
        ADesc.RedPrec := 5;
 
587
        ADesc.GreenPrec := 6;
 
588
        ADesc.BluePrec := 5;
 
589
        ADesc.RedShift := 11;
 
590
        ADesc.GreenShift := 5;
 
591
        ADesc.BlueShift := 0;
 
592
        ADesc.Depth := 16;
 
593
      end;
 
594
    24:
 
595
      begin
 
596
        // 8-8-8 mode
 
597
        ADesc.RedPrec := 8;
 
598
        ADesc.GreenPrec := 8;
 
599
        ADesc.BluePrec := 8;
 
600
        ADesc.RedShift := 16;
 
601
        ADesc.GreenShift := 8;
 
602
        ADesc.BlueShift := 0;
 
603
      end;
 
604
  else    //  32:
 
605
    // 8-8-8-8 mode, high byte can be native alpha or custom 1bit maskalpha
 
606
    ADesc.AlphaPrec := 8;
 
607
    ADesc.RedPrec := 8;
 
608
    ADesc.GreenPrec := 8;
 
609
    ADesc.BluePrec := 8;
 
610
    ADesc.AlphaShift := 24;
 
611
    ADesc.RedShift := 16;
 
612
    ADesc.GreenShift := 8;
 
613
    ADesc.BlueShift := 0;
 
614
    ADesc.Depth := 32;
 
615
  end;
 
616
end;
 
617
 
 
618
 
 
619
procedure FillRawImageDescription(const ABitmapInfo: Windows.TBitmap; out ADesc: TRawImageDescription);
 
620
begin
 
621
  ADesc.Init;
 
622
 
 
623
  ADesc.Format := ricfRGBA;
 
624
 
 
625
  ADesc.Depth := ABitmapInfo.bmBitsPixel;             // used bits per pixel
 
626
  ADesc.Width := ABitmapInfo.bmWidth;
 
627
  ADesc.Height := ABitmapInfo.bmHeight;
 
628
  ADesc.BitOrder := riboReversedBits;
 
629
  ADesc.ByteOrder := riboLSBFirst;
 
630
  ADesc.LineOrder := riloTopToBottom;
 
631
  ADesc.BitsPerPixel := ABitmapInfo.bmBitsPixel;      // bits per pixel. can be greater than Depth.
 
632
  ADesc.LineEnd := rileDWordBoundary;
 
633
 
 
634
  if ABitmapInfo.bmBitsPixel <= 8
 
635
  then begin
 
636
    // each pixel is an index in the palette
 
637
    // TODO, ColorCount
 
638
    ADesc.PaletteColorCount := 0;
 
639
  end
 
640
  else ADesc.PaletteColorCount := 0;
 
641
 
 
642
  FillRawImageDescriptionColors(ADesc);
 
643
 
 
644
  ADesc.MaskBitsPerPixel := 1;
 
645
  ADesc.MaskShift := 0;
 
646
  ADesc.MaskLineEnd := rileWordBoundary; // CreateBitmap requires word boundary
 
647
  ADesc.MaskBitOrder := riboReversedBits;
 
648
end;
 
649
 
 
650
function WinProc_RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean;
 
651
var
 
652
  WinDIB: Windows.TDIBSection;
 
653
  WinBmp: Windows.TBitmap absolute WinDIB.dsBm;
 
654
  ASize: Integer;
 
655
  R: TRect;
 
656
begin
 
657
  ARawImage.Init;
 
658
  FillChar(WinDIB, SizeOf(WinDIB), 0);
 
659
  ASize := Windows.GetObject(ABitmap, SizeOf(WinDIB), @WinDIB);
 
660
  if ASize = 0
 
661
  then Exit(False);
 
662
 
 
663
  //DbgDumpBitmap(ABitmap, 'FromBitmap - Image');
 
664
  //DbgDumpBitmap(AMask, 'FromMask - Mask');
 
665
 
 
666
  FillRawImageDescription(WinBmp, ARawImage.Description);
 
667
  // if it is not DIB then alpha in bitmaps is not supported => use 0 alpha prec
 
668
  if ASize < SizeOf(WinDIB) then
 
669
    ARawImage.Description.AlphaPrec := 0;
 
670
 
 
671
  if ARect = nil
 
672
  then begin
 
673
    R := Rect(0, 0, WinBmp.bmWidth, WinBmp.bmHeight);
 
674
  end
 
675
  else begin
 
676
    R := ARect^;
 
677
    if R.Top > WinBmp.bmHeight then
 
678
      R.Top := WinBmp.bmHeight;
 
679
    if R.Bottom > WinBmp.bmHeight then
 
680
      R.Bottom := WinBmp.bmHeight;
 
681
    if R.Left > WinBmp.bmWidth then
 
682
      R.Left := WinBmp.bmWidth;
 
683
    if R.Right > WinBmp.bmWidth then
 
684
      R.Right := WinBmp.bmWidth;
 
685
  end;
 
686
 
 
687
  ARawImage.Description.Width := R.Right - R.Left;
 
688
  ARawImage.Description.Height := R.Bottom - R.Top;
 
689
 
 
690
  // copy bitmap
 
691
  Result := GetBitmapBytes(WinBmp, ABitmap, R, ARawImage.Description.LineEnd, ARawImage.Description.LineOrder, ARawImage.Data, ARawImage.DataSize);
 
692
 
 
693
  // check mask
 
694
  if AMask <> 0 then
 
695
  begin
 
696
    if Windows.GetObject(AMask, SizeOf(WinBmp), @WinBmp) = 0
 
697
    then Exit(False);
 
698
 
 
699
    Result := GetBitmapBytes(WinBmp, AMask, R, ARawImage.Description.MaskLineEnd, ARawImage.Description.LineOrder, ARawImage.Mask, ARawImage.MaskSize);
 
700
  end
 
701
  else begin
 
702
    ARawImage.Description.MaskBitsPerPixel := 0;
 
703
  end;
 
704
end;
 
705
 
 
706
{------------------------------------------------------------------------------
 
707
  Function: RawImage_CreateBitmaps
 
708
  Params: ARawImage:
 
709
          ABitmap:
 
710
          AMask:
 
711
          ASkipMask: When set there is no mask created
 
712
  Returns:
 
713
 
 
714
 ------------------------------------------------------------------------------}
 
715
{$ifdef WinCE}
 
716
function WinProc_RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean;
 
717
var
 
718
  ADesc: TRawImageDescription absolute ARawImage.Description;
 
719
  DC: HDC;
 
720
  BitsPtr: Pointer;
 
721
  DataSize: PtrUInt;
 
722
begin
 
723
  Result := False;
 
724
  AMask := 0;
 
725
 
 
726
  if not ((ADesc.BitsPerPixel = 1) and (ADesc.LineEnd = rileWordBoundary)) then
 
727
  begin
 
728
    DC := Windows.GetDC(0);
 
729
    AMask := 0;
 
730
    ABitmap := CreateDIBSectionFromDescription(DC, ADesc, BitsPtr);
 
731
    //DbgDumpBitmap(ABitmap, 'CreateBitmaps - Image');
 
732
    Windows.ReleaseDC(0, DC);
 
733
 
 
734
    Result := ABitmap <> 0;
 
735
    if not Result then Exit;
 
736
    if BitsPtr = nil then Exit;
 
737
 
 
738
    // copy the image data
 
739
    DataSize := BytesPerLine(ADesc.Width, ADesc.BitsPerPixel) * ADesc.Height;
 
740
    if DataSize > ARawImage.DataSize
 
741
    then DataSize := ARawImage.DataSize;
 
742
    Move(ARawImage.Data^, BitsPtr^, DataSize);
 
743
  end
 
744
  else
 
745
    ABitmap := Windows.CreateBitmap(ADesc.Width, ADesc.Height, 1, 1, ARawImage.Data);
 
746
 
 
747
  if ASkipMask then Exit(True);
 
748
 
 
749
  AMask := Windows.CreateBitmap(ADesc.Width, ADesc.Height, 1, 1, ARawImage.Mask);
 
750
  //DbgDumpBitmap(ABitmap, 'CreateBitmaps - Mask');
 
751
  Result := AMask <> 0;
 
752
end;
 
753
{$else}
 
754
function WinProc_RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean;
 
755
var
 
756
  ADesc: TRawImageDescription absolute ARawImage.Description;
 
757
 
 
758
  function DoBitmap: Boolean;
 
759
  var
 
760
    DC: HDC;
 
761
    Info: record
 
762
      Header: Windows.TBitmapInfoHeader;
 
763
      Colors: array[0..1] of Cardinal; // reserve extra color for mono bitmaps
 
764
    end;
 
765
    DstLinePtr, SrcLinePtr: PByte;
 
766
    SrcPixelPtr, DstPixelPtr: PByte;
 
767
    DstLineSize, SrcLineSize: PtrUInt;
 
768
    x, y: Integer;
 
769
    Ridx, Gidx, Bidx, Aidx, Align, SrcBytes, DstBpp: Byte;
 
770
  begin
 
771
    if (ADesc.BitsPerPixel = 1) and (ADesc.LineEnd = rileWordBoundary)
 
772
    then begin
 
773
      // default BW, word aligned bitmap
 
774
      ABitmap := Windows.CreateBitmap(ADesc.Width, ADesc.Height, 1, 1, ARawImage.Data);
 
775
      Exit(ABitmap <> 0);
 
776
    end;
 
777
 
 
778
    // for 24 bits images, BPP can be 24 or 32
 
779
    // 32 shouldn't be use since we don't fill the alpha channel
 
780
 
 
781
    if ADesc.Depth = 24
 
782
    then DstBpp := 24
 
783
    else DstBpp := ADesc.BitsPerPixel;
 
784
 
 
785
    FillChar(Info, SizeOf(Info), 0);
 
786
    Info.Header.biSize := SizeOf(Info.Header);
 
787
    Info.Header.biWidth := ADesc.Width;
 
788
    if ADesc.LineOrder = riloTopToBottom
 
789
    then Info.Header.biHeight := -ADesc.Height // create top to bottom
 
790
    else Info.Header.biHeight := ADesc.Height; // create bottom to top
 
791
    Info.Header.biPlanes := 1;
 
792
    Info.Header.biBitCount := DstBpp;
 
793
    Info.Header.biCompression := BI_RGB;
 
794
    {Info.Header.biSizeImage := 0;}
 
795
    { first color is black, second color is white, for monochrome bitmap }
 
796
    Info.Colors[1] := $FFFFFFFF;
 
797
 
 
798
    DC := Windows.GetDC(0);
 
799
    // Use createDIBSection, since only devicedepth bitmaps can be selected into a DC
 
800
    // when they are created with createDIBitmap
 
801
    //  ABitmap := Windows.CreateDIBitmap(DC, Info.Header, CBM_INIT, ARawImage.Data, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS);
 
802
    ABitmap := Windows.CreateDIBSection(DC, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS, DstLinePtr, 0, 0);
 
803
    Windows.ReleaseDC(0, DC);
 
804
 
 
805
    if ABitmap = 0
 
806
    then begin
 
807
      DebugLn('Windows.CreateDIBSection returns 0. Reason = ' + GetLastErrorText(Windows.GetLastError));
 
808
      Exit(False);
 
809
    end;
 
810
    if DstLinePtr = nil then Exit(False);
 
811
 
 
812
    DstLineSize := Windows.MulDiv(DstBpp, ADesc.Width, 8);
 
813
    // align to DWord
 
814
    Align := DstLineSize and 3;
 
815
    if Align > 0
 
816
    then Inc(DstLineSize, 4 - Align);
 
817
 
 
818
    SrcLinePtr := ARawImage.Data;
 
819
    SrcLineSize := ADesc.BytesPerLine;
 
820
 
 
821
    // copy the image data
 
822
    if ADesc.Depth >= 24
 
823
    then begin
 
824
      // check if a pixel copy is needed
 
825
      // 1) Windows uses alpha channel in 32 bpp modes, despite documentation statement that it is ignored. Tested under Windows XP SP3
 
826
      // Wine also relies on this undocumented behaviour!
 
827
      // So, we need to cut unused A-channel, otherwise we would get black image
 
828
      //
 
829
      // 2) incompatible channel order
 
830
      ADesc.GetRGBIndices(Ridx, Gidx, Bidx, Aidx);
 
831
 
 
832
      if ((ADesc.BitsPerPixel = 32) and (ADesc.Depth = 24))
 
833
      or (Bidx <> 0) or (Gidx <> 1) or (Ridx <> 2)
 
834
      then begin
 
835
        // copy pixels
 
836
        SrcBytes := ADesc.BitsPerPixel div 8;
 
837
 
 
838
        for y := 0 to ADesc.Height - 1 do
 
839
        begin
 
840
          DstPixelPtr := DstLinePtr;
 
841
          SrcPixelPtr := SrcLinePtr;
 
842
          for x := 0 to ADesc.Width - 1 do
 
843
          begin
 
844
            DstPixelPtr[0] := SrcPixelPtr[Bidx];
 
845
            DstPixelPtr[1] := SrcPixelPtr[Gidx];
 
846
            DstPixelPtr[2] := SrcPixelPtr[Ridx];
 
847
 
 
848
            Inc(DstPixelPtr, 3); //move to the next dest RGB triple
 
849
            Inc(SrcPixelPtr, SrcBytes);
 
850
          end;
 
851
 
 
852
          Inc(DstLinePtr, DstLineSize);
 
853
          Inc(SrcLinePtr, SrcLineSize);
 
854
        end;
 
855
 
 
856
        Exit(True);
 
857
      end;
 
858
    end;
 
859
 
 
860
    // no pixelcopy needed
 
861
    // check if we can move using one call
 
862
    if ADesc.LineEnd = rileDWordBoundary
 
863
    then begin
 
864
      Move(SrcLinePtr^, DstLinePtr^, DstLineSize * ADesc.Height);
 
865
      Exit(True);
 
866
    end;
 
867
 
 
868
    //Can't use just one move, as different alignment
 
869
    for y := 0 to ADesc.Height - 1 do
 
870
    begin
 
871
      Move(SrcLinePtr^, DstLinePtr^, DstLineSize);
 
872
      Inc(DstLinePtr, DstLineSize);
 
873
      Inc(SrcLinePtr, SrcLineSize);
 
874
    end;
 
875
 
 
876
    Result := True;
 
877
  end;
 
878
 
 
879
begin
 
880
  AMask := 0;
 
881
  Result := DoBitmap;
 
882
  if not Result then Exit;
 
883
 
 
884
  //DbgDumpBitmap(ABitmap, 'CreateBitmaps - Image');
 
885
  if ASkipMask then Exit;
 
886
 
 
887
  AMask := Windows.CreateBitmap(ADesc.Width, ADesc.Height, 1, 1, ARawImage.Mask);
 
888
  if AMask = 0 then
 
889
    DebugLn('Windows.CreateBitmap returns 0. Reason = ' + GetLastErrorText(Windows.GetLastError));
 
890
  Result := AMask <> 0;
 
891
  //DbgDumpBitmap(AMask, 'CreateBitmaps - Mask');
 
892
end;
 
893
{$endif}
 
894
 
 
895
function CreateDIBSectionFromDescription(ADC: HDC; const ADesc: TRawImageDescription; out ABitsPtr: Pointer): HBITMAP;
 
896
  function GetMask(APrec, AShift: Byte): Cardinal;
 
897
  begin
 
898
    Result := ($FFFFFFFF shr (32-APrec)) shl AShift;
 
899
  end;
 
900
 
 
901
var
 
902
  Info: record
 
903
    Header: Windows.TBitmapInfoHeader;
 
904
    Colors: array[0..3] of Cardinal; // reserve extra color for colormasks
 
905
  end;
 
906
begin
 
907
  FillChar(Info, sizeof(Info), 0);
 
908
  Info.Header.biSize := sizeof(Windows.TBitmapInfoHeader);
 
909
  Info.Header.biWidth := ADesc.Width;
 
910
  Info.Header.biHeight := -ADesc.Height;
 
911
  Info.Header.biPlanes := 1;
 
912
  Info.Header.biBitCount := ADesc.BitsPerPixel;
 
913
  // TODO: palette support
 
914
  Info.Header.biClrUsed := 0;
 
915
  Info.Header.biClrImportant := 0;
 
916
  Info.Header.biSizeImage := BytesPerLine(Info.Header.biWidth, Info.Header.biBitCount) * ADesc.Height;
 
917
  // CE only supports bitfields
 
918
  if ADesc.BitsPerPixel > 8
 
919
  then Info.Header.biCompression := BI_BITFIELDS
 
920
  else Info.Header.biCompression := BI_RGB;
 
921
 
 
922
  if ADesc.BitsPerPixel = 1
 
923
  then begin
 
924
    // mono bitmap: first color is black, second is white
 
925
    Info.Colors[1] := $FFFFFFFF;
 
926
  end
 
927
  else begin
 
928
    // when 24bpp, CE only supports B8G8R8 encoding
 
929
    // TODO: check the description
 
930
    Info.Colors[0] := GetMask(ADesc.RedPrec, ADesc.RedShift);
 
931
    Info.Colors[1] := GetMask(ADesc.GreenPrec, ADesc.GreenShift);
 
932
    Info.Colors[2] := GetMask(ADesc.BluePrec, ADesc.BlueShift);
 
933
  end;
 
934
 
 
935
  // Use createDIBSection, since only devicedepth bitmaps can be selected into a DC
 
936
  // when they are created with createDIBitmap
 
937
  Result := Windows.CreateDIBSection(ADC, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS, ABitsPtr, 0, 0);
 
938
 
 
939
  //DbgDumpBitmap(Result, 'CreateDIBSectionFromDescription - Image');
 
940
end;
 
941
 
 
942
function CreateDIBSectionFromDDB(ASource: HBitmap; out ABitsPtr: Pointer): HBitmap;
 
943
var
 
944
  ADC, SrcDC, DstDC: HDC;
 
945
  ADesc: TRawImageDescription;
 
946
  SrcOldBm, DstOldBm: HBitmap;
 
947
begin
 
948
  Result := 0;
 
949
 
 
950
  // get source bitmap description
 
951
  if not RawImage_DescriptionFromBitmap(ASource, ADesc) then
 
952
    Exit;
 
953
 
 
954
  // create apropriate dib section
 
955
  ADC := GetDC(0);
 
956
  Result := CreateDIBSectionFromDescription(ADC, ADesc, ABitsPtr);
 
957
  ReleaseDC(0, ADC);
 
958
 
 
959
  if Result = 0 then
 
960
    Exit;
 
961
 
 
962
  // copy source bitmap into destination
 
963
  SrcDC := CreateCompatibleDC(0);
 
964
  SrcOldBm := SelectObject(SrcDC, ASource);
 
965
  DstDC := CreateCompatibleDC(0);
 
966
  DstOldBm := SelectObject(DstDC, Result);
 
967
  Windows.BitBlt(DstDC, 0, 0, ADesc.Width, ADesc.Height, SrcDC, 0, 0, SRCCOPY);
 
968
  SelectObject(SrcDC, SrcOldBm);
 
969
  SelectObject(DstDC, DstOldBm);
 
970
  DeleteDC(SrcDC);
 
971
  DeleteDC(DstDC);
 
972
end;
 
973
 
 
974
{$ifndef Wince}
 
975
function GetBitmapOrder(AWinBmp: Windows.TBitmap; ABitmap: HBITMAP): TRawImageLineOrder;
 
976
  procedure DbgLog(const AFunc: String);
 
977
  begin
 
978
    DebugLn('GetBitmapOrder - GetDIBits ', AFunc, ' failed: ', GetLastErrorText(Windows.GetLastError));
 
979
  end;
 
980
 
 
981
var
 
982
  SrcPixel: PCardinal absolute AWinBmp.bmBits;
 
983
  OrgPixel, TstPixel: Cardinal;
 
984
  Scanline: Pointer;
 
985
  DC: HDC;
 
986
  Info: record
 
987
    Header: Windows.TBitmapInfoHeader;
 
988
    Colors: array[Byte] of Cardinal; // reserve extra color for colormasks
 
989
  end;
 
990
 
 
991
  FullScanLine: Boolean; // win9x requires a full scanline to be retrieved
 
992
                         // others won't fail when one pixel is requested
 
993
begin
 
994
  if AWinBmp.bmBits = nil
 
995
  then begin
 
996
    // no DIBsection so always bottom-up
 
997
    Exit(riloBottomToTop);
 
998
  end;
 
999
 
 
1000
  // try to figure out the orientation of the given bitmap.
 
1001
  // Unfortunately MS doesn't provide a direct function for this.
 
1002
  // So modify the first pixel to see if it changes. This pixel is always part
 
1003
  // of the first scanline of the given bitmap.
 
1004
  // When we request the data through GetDIBits as bottom-up, windows adjusts
 
1005
  // the data when it is a top-down. So if the pixel doesn't change the bitmap
 
1006
  // was internally a top-down image.
 
1007
 
 
1008
  FullScanLine := Win32Platform = VER_PLATFORM_WIN32_WINDOWS;
 
1009
  if FullScanLine
 
1010
  then ScanLine := GetMem(AWinBmp.bmWidthBytes);
 
1011
 
 
1012
  FillChar(Info.Header, sizeof(Windows.TBitmapInfoHeader), 0);
 
1013
  Info.Header.biSize := sizeof(Windows.TBitmapInfoHeader);
 
1014
  DC := Windows.GetDC(0);
 
1015
  if Windows.GetDIBits(DC, ABitmap, 0, 1, nil, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS) = 0
 
1016
  then begin
 
1017
    DbgLog('Getinfo');
 
1018
    // failed ???
 
1019
    Windows.ReleaseDC(0, DC);
 
1020
    Exit(riloBottomToTop);
 
1021
  end;
 
1022
 
 
1023
  // Get only 1 pixel (or full scanline for win9x)
 
1024
  OrgPixel := 0;
 
1025
  if FullScanLine
 
1026
  then begin
 
1027
    if Windows.GetDIBits(DC, ABitmap, 0, 1, ScanLine, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS) = 0
 
1028
    then DbgLog('OrgPixel')
 
1029
    else OrgPixel := PCardinal(ScanLine)^;
 
1030
  end
 
1031
  else begin
 
1032
    Info.Header.biWidth := 1;
 
1033
    if Windows.GetDIBits(DC, ABitmap, 0, 1, @OrgPixel, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS) = 0
 
1034
    then DbgLog('OrgPixel');
 
1035
  end;
 
1036
 
 
1037
  // modify pixel
 
1038
  SrcPixel^ := not SrcPixel^;
 
1039
 
 
1040
  // get test
 
1041
  TstPixel := 0;
 
1042
  if FullScanLine
 
1043
  then begin
 
1044
    if Windows.GetDIBits(DC, ABitmap, 0, 1, ScanLine, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS) = 0
 
1045
    then DbgLog('TstPixel')
 
1046
    else TstPixel := PCardinal(ScanLine)^;
 
1047
  end
 
1048
  else begin
 
1049
    if Windows.GetDIBits(DC, ABitmap, 0, 1, @TstPixel, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS) = 0
 
1050
    then DbgLog('TstPixel');
 
1051
  end;
 
1052
 
 
1053
  if OrgPixel = TstPixel
 
1054
  then Result := riloTopToBottom
 
1055
  else Result := riloBottomToTop;
 
1056
 
 
1057
  // restore pixel & cleanup
 
1058
  SrcPixel^ := not SrcPixel^;
 
1059
  Windows.ReleaseDC(0, DC);
 
1060
  if FullScanLine
 
1061
  then FreeMem(Scanline);
 
1062
end;
 
1063
{$endif}
 
1064
 
 
1065
{$ifdef WinCE}
 
1066
//function GetBitmapBytes(ABitmap: HBITMAP; const ARect: TRect; ALineEnd: TRawImageLineEnd; var AData: Pointer; var ADataSize: PtrUInt): Boolean;
 
1067
function GetBitmapBytes(AWinBmp: Windows.TBitmap; ABitmap: HBITMAP; const ARect: TRect; ALineEnd: TRawImageLineEnd; ALineOrder: TRawImageLineOrder; out AData: Pointer; out ADataSize: PtrUInt): Boolean;
 
1068
var
 
1069
  Section: Windows.TDIBSection;
 
1070
  DIBCopy: HBitmap;
 
1071
  DIBData: Pointer;
 
1072
begin
 
1073
  Result := False;
 
1074
  // first try if the bitmap is created as section
 
1075
  if (Windows.GetObject(ABitmap, SizeOf(Section), @Section) > 0) and (Section.dsBm.bmBits <> nil)
 
1076
  then begin
 
1077
    with Section.dsBm do
 
1078
      Result := CopyImageData(bmWidth, bmHeight, bmWidthBytes, bmBitsPixel, bmBits, ARect, riloTopToBottom, riloTopToBottom, ALineEnd, AData, ADataSize);
 
1079
    Exit;
 
1080
  end;
 
1081
 
 
1082
  // bitmap is not a section, retrieve only bitmap
 
1083
  if Windows.GetObject(ABitmap, SizeOf(Section.dsBm), @Section) = 0
 
1084
  then Exit;
 
1085
 
 
1086
  DIBCopy := CreateDIBSectionFromDDB(ABitmap, DIBData);
 
1087
  if DIBCopy = 0 then
 
1088
    Exit;
 
1089
  if (Windows.GetObject(DIBCopy, SizeOf(Section), @Section) > 0) and (Section.dsBm.bmBits <> nil)
 
1090
  then begin
 
1091
    with Section.dsBm do
 
1092
      Result := CopyImageData(bmWidth, bmHeight, bmWidthBytes, bmBitsPixel, bmBits, ARect, riloTopToBottom, riloTopToBottom, ALineEnd, AData, ADataSize);
 
1093
  end;
 
1094
 
 
1095
  DeleteObject(DIBCopy);
 
1096
 
 
1097
  Result := True;
 
1098
end;
 
1099
{$else}
 
1100
function GetBitmapBytes(AWinBmp: Windows.TBitmap; ABitmap: HBITMAP; const ARect: TRect; ALineEnd: TRawImageLineEnd; ALineOrder: TRawImageLineOrder; out AData: Pointer; out ADataSize: PtrUInt): Boolean;
 
1101
var
 
1102
  DC: HDC;
 
1103
  Info: record
 
1104
    Header: Windows.TBitmapInfoHeader;
 
1105
    Colors: array[Byte] of TRGBQuad; // reserve extra colors for palette (256 max)
 
1106
  end;
 
1107
  H: Cardinal;
 
1108
  R: TRect;
 
1109
  SrcData: PByte;
 
1110
  SrcSize: PtrUInt;
 
1111
  SrcLineBytes: Cardinal;
 
1112
  SrcLineOrder: TRawImageLineOrder;
 
1113
  StartScan: Integer;
 
1114
begin
 
1115
  SrcLineOrder := GetBitmapOrder(AWinBmp, ABitmap);
 
1116
  SrcLineBytes := (AWinBmp.bmWidthBytes + 3) and not 3;
 
1117
 
 
1118
  if AWinBmp.bmBits <> nil
 
1119
  then begin
 
1120
    // this is bitmapsection data :) we can just copy the bits
 
1121
 
 
1122
    // We cannot trust windows with bmWidthBytes. Use SrcLineBytes which takes
 
1123
    // DWORD alignment into consideration
 
1124
    with AWinBmp do
 
1125
      Result := CopyImageData(bmWidth, bmHeight, SrcLineBytes, bmBitsPixel, bmBits, ARect, SrcLineOrder, ALineOrder, ALineEnd, AData, ADataSize);
 
1126
    Exit;
 
1127
  end;
 
1128
 
 
1129
  // retrieve the data though GetDIBits
 
1130
 
 
1131
  // initialize bitmapinfo structure
 
1132
  Info.Header.biSize := sizeof(Info.Header);
 
1133
  Info.Header.biPlanes := 1;
 
1134
  Info.Header.biBitCount := AWinBmp.bmBitsPixel;
 
1135
  Info.Header.biCompression := BI_RGB;
 
1136
  Info.Header.biSizeImage := 0;
 
1137
 
 
1138
  Info.Header.biWidth := AWinBmp.bmWidth;
 
1139
  H := ARect.Bottom - ARect.Top;
 
1140
  // request a top-down DIB
 
1141
  if AWinBmp.bmHeight > 0
 
1142
  then begin
 
1143
    Info.Header.biHeight := -AWinBmp.bmHeight;
 
1144
    StartScan := AWinBmp.bmHeight - ARect.Bottom;
 
1145
  end
 
1146
  else begin
 
1147
    Info.Header.biHeight := AWinBmp.bmHeight;
 
1148
    StartScan := ARect.Top;
 
1149
  end;
 
1150
  // adjust height
 
1151
  if StartScan < 0
 
1152
  then begin
 
1153
    Inc(H, StartScan);
 
1154
    StartScan := 0;
 
1155
  end;
 
1156
 
 
1157
  // alloc buffer
 
1158
  SrcSize := SrcLineBytes * H;
 
1159
  GetMem(SrcData, SrcSize);
 
1160
 
 
1161
  DC := Windows.GetDC(0);
 
1162
  Result := Windows.GetDIBits(DC, ABitmap, StartScan, H, SrcData, Windows.PBitmapInfo(@Info)^, DIB_RGB_COLORS) <> 0;
 
1163
  Windows.ReleaseDC(0, DC);
 
1164
 
 
1165
  // since we only got the needed scanlines, adjust top and bottom
 
1166
  R.Left := ARect.Left;
 
1167
  R.Top := 0;
 
1168
  R.Right := ARect.Right;
 
1169
  R.Bottom := H;
 
1170
 
 
1171
  with Info.Header do
 
1172
    Result := Result and CopyImageData(biWidth, H, SrcLineBytes, biBitCount, SrcData, R, riloTopToBottom, ALineOrder, ALineEnd, AData, ADataSize);
 
1173
 
 
1174
  FreeMem(SrcData);
 
1175
end;
 
1176
{$endif}
 
1177
 
 
1178
function IsAlphaBitmap(ABitmap: HBITMAP): Boolean;
 
1179
var
 
1180
  Info: Windows.BITMAP;
 
1181
begin
 
1182
  FillChar(Info, SizeOf(Info), 0);
 
1183
  Result := (GetObject(ABitmap, SizeOf(Info), @Info) <> 0)
 
1184
        and (Info.bmBitsPixel = 32);
 
1185
end;
 
1186
 
 
1187
function IsAlphaDC(ADC: HDC): Boolean;
 
1188
begin
 
1189
  Result := (GetObjectType(ADC) = OBJ_MEMDC)
 
1190
        and IsAlphaBitmap(GetCurrentObject(ADC, OBJ_BITMAP));
 
1191
end;
 
1192
 
 
1193
function GetLastErrorText(AErrorCode: Cardinal): WideString;
 
1194
var
 
1195
  r: cardinal;
 
1196
  tmp: PWideChar;
 
1197
begin
 
1198
  tmp := nil;
 
1199
  r := Windows.FormatMessage(
 
1200
    FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ARGUMENT_ARRAY,
 
1201
    nil, AErrorCode, LANG_NEUTRAL, @tmp, 0, nil);
 
1202
 
 
1203
  if r = 0 then Exit('');
 
1204
 
 
1205
  Result := tmp;
 
1206
  SetLength(Result, Length(Result)-2);
 
1207
 
 
1208
  if tmp <> nil
 
1209
  then LocalFree(HLOCAL(tmp));
 
1210
end;
 
1211
 
 
1212
(***********************************************************************
 
1213
  Widget member Functions
 
1214
************************************************************************)
 
1215
 
 
1216
{-------------------------------------------------------------------------------
 
1217
  function LCLBoundsNeedsUpdate(Sender: TWinControl;
 
1218
    SendSizeMsgOnDiff: boolean): boolean;
 
1219
 
 
1220
  Returns true if LCL bounds and win32 bounds differ for the control.
 
1221
-------------------------------------------------------------------------------}
 
1222
function LCLControlSizeNeedsUpdate(Sender: TWinControl;
 
1223
  SendSizeMsgOnDiff: boolean): boolean;
 
1224
var
 
1225
  Window:HWND;
 
1226
  LMessage: TLMSize;
 
1227
  IntfWidth, IntfHeight: integer;
 
1228
begin
 
1229
  Result:=false;
 
1230
  Window:= Sender.Handle;
 
1231
  LCLIntf.GetWindowSize(Window, IntfWidth, IntfHeight);
 
1232
  if (Sender.Width = IntfWidth)
 
1233
  and (Sender.Height = IntfHeight)
 
1234
  and (not Sender.ClientRectNeedsInterfaceUpdate) then
 
1235
    exit;
 
1236
  Result:=true;
 
1237
  if SendSizeMsgOnDiff then
 
1238
  begin
 
1239
    //writeln('LCLBoundsNeedsUpdate B ',TheWinControl.Name,':',TheWinControl.ClassName,' Sending WM_SIZE');
 
1240
    Sender.InvalidateClientRectCache(true);
 
1241
    // send message directly to LCL, some controls not subclassed -> message
 
1242
    // never reaches LCL
 
1243
    with LMessage do
 
1244
    begin
 
1245
      Msg := LM_SIZE;
 
1246
      SizeType := SIZE_RESTORED or Size_SourceIsInterface;
 
1247
      Width := IntfWidth;
 
1248
      Height := IntfHeight;
 
1249
    end;
 
1250
    DeliverMessage(Sender, LMessage);
 
1251
  end;
 
1252
end;
 
1253
 
 
1254
{-------------------------------------------------------------------------------
 
1255
  function GetLCLClientOriginOffset(Sender: TObject;
 
1256
    var LeftOffset, TopOffset: integer): boolean;
 
1257
 
 
1258
  Returns the difference between the client origin of a win32 handle
 
1259
  and the definition of the LCL counterpart.
 
1260
  For example:
 
1261
    TGroupBox's client area is the area inside the groupbox frame.
 
1262
    Hence, the LeftOffset is the frame width and the TopOffset is the caption
 
1263
    height.
 
1264
-------------------------------------------------------------------------------}
 
1265
function GetLCLClientBoundsOffset(Sender: TObject; var ORect: TRect): boolean;
 
1266
var
 
1267
  TM: TextMetric;
 
1268
  DC: HDC;
 
1269
  Handle: HWND;
 
1270
  TheWinControl: TWinControl;
 
1271
  ARect: TRect;
 
1272
  Ignore: Integer;
 
1273
begin
 
1274
  Result:=false;
 
1275
  if (Sender = nil) or (not (Sender is TWinControl)) then exit;
 
1276
  TheWinControl:=TWinControl(Sender);
 
1277
  FillChar(ORect, SizeOf(ORect), 0);
 
1278
  if not TheWinControl.HandleAllocated then exit;
 
1279
  Handle := TheWinControl.Handle;
 
1280
  if TheWinControl is TScrollingWinControl then
 
1281
    with TScrollingWinControl(TheWinControl) do
 
1282
    begin
 
1283
      if HorzScrollBar <> nil then
 
1284
      begin
 
1285
        // left and right bounds are shifted by scroll position
 
1286
        ORect.Left := -HorzScrollBar.Position;
 
1287
        ORect.Right := -HorzScrollBar.Position;
 
1288
      end;
 
1289
      if VertScrollBar <> nil then
 
1290
      begin
 
1291
        // top and bottom bounds are shifted by scroll position
 
1292
        ORect.Top := -VertScrollBar.Position;
 
1293
        ORect.Bottom := -VertScrollBar.Position;
 
1294
      end;
 
1295
    end;
 
1296
 
 
1297
  {$ifdef DEBUG_WINDOW_ORG}
 
1298
  DebugLn(
 
1299
    Format('GetLCLClientBoundsOffset Name=%s OLeft=%d OTop=%d ORight=%d OBottom=%d',
 
1300
     [TheWinControl.Name, ORect.Left, ORect.Top, ORect.Right, ORect.Bottom]));
 
1301
  {$endif}
 
1302
 
 
1303
  Result := True;
 
1304
end;
 
1305
 
 
1306
function GetLCLClientBoundsOffset(Handle: TWindowInfo; var Rect: TRect): boolean;
 
1307
var
 
1308
  OwnerObject: TObject;
 
1309
begin
 
1310
  OwnerObject := TWindowInfo(Handle).LCLForm;
 
1311
  Result:=GetLCLClientBoundsOffset(OwnerObject, Rect);
 
1312
end;
 
1313
 
 
1314
procedure LCLBoundsToWin32Bounds(Sender: TObject;
 
1315
  var Left, Top, Width, Height: Integer);
 
1316
var
 
1317
  ORect: TRect;
 
1318
Begin
 
1319
  if (Sender=nil) or (not (Sender is TWinControl)) then exit;
 
1320
  if not GetLCLClientBoundsOffset(TWinControl(Sender).Parent, ORect) then exit;
 
1321
  inc(Left, ORect.Left);
 
1322
  inc(Top, ORect.Top);
 
1323
End;
 
1324
 
 
1325
procedure LCLFormSizeToWin32Size(Form: TCustomForm; var AWidth, AHeight: Integer);
 
1326
{$NOTE Should be moved to WSWin32Forms, if the windowproc is splitted}
 
1327
var
 
1328
  SizeRect: Windows.RECT;
 
1329
  BorderStyle: TFormBorderStyle;
 
1330
begin
 
1331
  with SizeRect do
 
1332
  begin
 
1333
    Left := 0;
 
1334
    Top := 0;
 
1335
    Right := AWidth;
 
1336
    Bottom := AHeight;
 
1337
  end;
 
1338
  BorderStyle := Form.BorderStyle;
 
1339
  Windows.AdjustWindowRectEx(@SizeRect, BorderStyleToWinAPIFlags(
 
1340
      BorderStyle), false, BorderStyleToWinAPIFlagsEx(Form, BorderStyle));
 
1341
  AWidth := SizeRect.Right - SizeRect.Left;
 
1342
  AHeight := SizeRect.Bottom - SizeRect.Top;
 
1343
end;
 
1344
 
 
1345
procedure GetWin32ControlPos(Window, Parent: HWND; var Left, Top: integer);
 
1346
var
 
1347
  parRect, winRect: Windows.TRect;
 
1348
begin
 
1349
  Windows.GetWindowRect(Window, @winRect);
 
1350
  Windows.GetWindowRect(Parent, @parRect);
 
1351
  Left := winRect.Left - parRect.Left;
 
1352
  Top := winRect.Top - parRect.Top;
 
1353
end;
 
1354
 
 
1355
function GetWindowInfo(AWindow: HWND): TWindowInfo;
 
1356
begin
 
1357
  Result := TWindowInfo(FindFormWithNativeHandle(AWindow));
 
1358
  if Result = nil then Result := DefaultWindowInfo;
 
1359
end;
 
1360
 
 
1361
{
 
1362
  Updates the window style of the window indicated by Handle.
 
1363
  The new style is the Style parameter.
 
1364
  Only the bits set in the StyleMask are changed,
 
1365
  the other bits remain untouched.
 
1366
  If the bits in the StyleMask are not used in the Style,
 
1367
  there are cleared.
 
1368
}
 
1369
procedure UpdateWindowStyle(Handle: HWnd; Style: integer; StyleMask: integer);
 
1370
var
 
1371
  CurrentStyle,
 
1372
  NewStyle : PtrInt;
 
1373
begin
 
1374
  CurrentStyle := Windows.GetWindowLong(Handle, GWL_STYLE);
 
1375
  NewStyle := (Style and StyleMask) or (CurrentStyle and (not StyleMask));
 
1376
  Windows.SetWindowLong(Handle, GWL_STYLE, NewStyle);
 
1377
end;
 
1378
 
 
1379
function BorderStyleToWinAPIFlags(Style: TFormBorderStyle): DWORD;
 
1380
begin
 
1381
  Result := WS_CLIPCHILDREN or WS_CLIPSIBLINGS;
 
1382
  case Application.ApplicationType of
 
1383
  { Under Desktop or Handheld mode we get an application which
 
1384
    looks similar to a desktop one, with sizable windows }
 
1385
    atDesktop:
 
1386
      begin
 
1387
        case Style of
 
1388
        bsSizeable, bsSizeToolWin:
 
1389
          Result := Result or (WS_OVERLAPPED or WS_THICKFRAME or WS_CAPTION);
 
1390
        bsSingle, bsToolWindow:
 
1391
          Result := Result or (WS_OVERLAPPED or WS_BORDER or WS_CAPTION);
 
1392
        bsDialog:
 
1393
          Result := Result or (WS_POPUP or WS_BORDER or WS_CAPTION);
 
1394
        bsNone:
 
1395
          Result := Result or WS_POPUP;
 
1396
        end;
 
1397
      end;
 
1398
    { Under PDA or Smartphone modes most windows are enlarged to fit the screen
 
1399
      Dialogs and borderless windows are exceptions }
 
1400
    atPDA, atKeyPadDevice, atDefault:
 
1401
      begin
 
1402
        case Style of
 
1403
        bsDialog:
 
1404
          Result := Result or (WS_POPUP or WS_BORDER or WS_CAPTION);
 
1405
        bsNone:
 
1406
          Result := Result or WS_POPUP;
 
1407
        else
 
1408
          Result := 0; // Never add WS_VISIBLE here, bug http://bugs.freepascal.org/view.php?id=12193
 
1409
        end;
 
1410
      end;
 
1411
  end;
 
1412
end;
 
1413
 
 
1414
function BorderStyleToWinAPIFlagsEx(AForm: TCustomForm; Style: TFormBorderStyle): DWORD;
 
1415
begin
 
1416
  Result := 0;
 
1417
 
 
1418
  case Application.ApplicationType of
 
1419
 
 
1420
    atDesktop:
 
1421
    begin
 
1422
      case Style of
 
1423
      bsDialog:
 
1424
        Result := WS_EX_DLGMODALFRAME or WS_EX_WINDOWEDGE;
 
1425
      bsToolWindow, bsSizeToolWin:
 
1426
        Result := WS_EX_TOOLWINDOW;
 
1427
      end;
 
1428
    end;
 
1429
 
 
1430
    atPDA, atKeyPadDevice, atDefault:
 
1431
    begin
 
1432
      {$ifdef WinCE}
 
1433
      // Adds an "OK" close button to the title bar instead of the standard
 
1434
      // "X" minimize button, unless the developer overrides that decision
 
1435
      case CDWidgetSet.WinCETitlePolicy of
 
1436
 
 
1437
        tpAlwaysUseOKButton: Result := WS_EX_CAPTIONOKBTN;
 
1438
 
 
1439
 
 
1440
        tpControlWithBorderIcons:
 
1441
        begin
 
1442
          if not (biMinimize in AForm.BorderIcons) then Result := WS_EX_CAPTIONOKBTN;
 
1443
        end;
 
1444
      else
 
1445
        if Style = bsDialog then Result := WS_EX_CAPTIONOKBTN;
 
1446
      end;
 
1447
      {$endif}
 
1448
    end;
 
1449
 
 
1450
  end;
 
1451
end;
 
1452
 
 
1453
function GetFileVersion(FileName: string): dword;
 
1454
var
 
1455
  buf: pointer;
 
1456
  lenBuf: dword;
 
1457
  fixedInfo: ^VS_FIXEDFILEINFO;
 
1458
  WideBuffer: widestring;
 
1459
begin
 
1460
  Result := $FFFFFFFF;
 
1461
  WideBuffer := UTF8Decode(FileName);
 
1462
  lenBuf := GetFileVersionInfoSizeW(PWideChar(WideBuffer), lenBuf);
 
1463
  if lenBuf > 0 then
 
1464
  begin
 
1465
    GetMem(buf, lenBuf);
 
1466
    if GetFileVersionInfoW(PWideChar(WideBuffer), 0, lenBuf, buf) then
 
1467
    begin
 
1468
      VerQueryValue(buf, '\', pointer(fixedInfo), lenBuf);
 
1469
      Result := fixedInfo^.dwFileVersionMS;
 
1470
    end;
 
1471
    FreeMem(buf);
 
1472
  end;
 
1473
end;
 
1474
 
 
1475
function EnumStayOnTopRemove(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
 
1476
var
 
1477
  StayOnTopWindowsInfo: PStayOnTopWindowsInfo absolute Param;
 
1478
  lWindowInfo: TWindowInfo;
 
1479
  lWinControl: TWinControl;
 
1480
begin
 
1481
{  Result := True;
 
1482
  if ((GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST) <> 0) then
 
1483
  begin
 
1484
    // Don't remove system-wide stay on top, unless desired
 
1485
    if not StayOnTopWindowsInfo^.SystemTopAlso then
 
1486
    begin
 
1487
      lWindowInfo := TWindowInfo(FindFormWithNativeHandle(Handle));
 
1488
      if Assigned(lWindowInfo) then
 
1489
      begin
 
1490
        lWinControl := lWindowInfo.LCLForm;
 
1491
        if (lWinControl is TCustomForm) and
 
1492
          (TCustomForm(lWinControl).FormStyle = fsSystemStayOnTop) then
 
1493
        Exit;
 
1494
      end;
 
1495
    end;
 
1496
 
 
1497
    StayOnTopWindowsInfo^.StayOnTopList.Add(Pointer(Handle));
 
1498
  end;}
 
1499
end;
 
1500
 
 
1501
procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False);
 
1502
var
 
1503
  StayOnTopWindowsInfo: PStayOnTopWindowsInfo;
 
1504
  WindowInfo: TWindowInfo;
 
1505
  I: Integer;
 
1506
begin
 
1507
{  //WriteLn('RemoveStayOnTopFlags ', InRemoveStayOnTopFlags);
 
1508
  if InRemoveStayOnTopFlags = 0 then
 
1509
  begin
 
1510
    New(StayOnTopWindowsInfo);
 
1511
    StayOnTopWindowsInfo^.AppHandle := AppHandle;
 
1512
    StayOnTopWindowsInfo^.SystemTopAlso := ASystemTopAlso;
 
1513
    StayOnTopWindowsInfo^.StayOnTopList := TList.Create;
 
1514
    WindowInfo := GetWindowInfo(AppHandle);
 
1515
    WindowInfo^.StayOnTopList := StayOnTopWindowsInfo^.StayOnTopList;
 
1516
    EnumThreadWindows(GetWindowThreadProcessId(AppHandle, nil),
 
1517
      @EnumStayOnTopRemove, LPARAM(StayOnTopWindowsInfo));
 
1518
    for I := 0 to WindowInfo^.StayOnTopList.Count - 1 do
 
1519
      SetWindowPos(HWND(WindowInfo^.StayOnTopList[I]), HWND_NOTOPMOST, 0, 0, 0, 0,
 
1520
        SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_DRAWFRAME);
 
1521
    Dispose(StayOnTopWindowsInfo);
 
1522
  end;
 
1523
  inc(InRemoveStayOnTopFlags);}
 
1524
end;
 
1525
 
 
1526
procedure RestoreStayOnTopFlags(AppHandle: HWND);
 
1527
var
 
1528
  WindowInfo: TWindowInfo;
 
1529
  I: integer;
 
1530
begin
 
1531
{  //WriteLn('RestoreStayOnTopFlags ', InRemoveStayOnTopFlags);
 
1532
  if InRemoveStayOnTopFlags = 1 then
 
1533
  begin
 
1534
    WindowInfo := GetWindowInfo(AppHandle);
 
1535
    if WindowInfo^.StayOnTopList <> nil then
 
1536
    begin
 
1537
      for I := 0 to WindowInfo^.StayOnTopList.Count - 1 do
 
1538
        SetWindowPos(HWND(WindowInfo^.StayOnTopList.Items[I]),
 
1539
          HWND_TOPMOST, 0, 0, 0, 0,
 
1540
          SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_DRAWFRAME);
 
1541
      FreeAndNil(WindowInfo^.StayOnTopList);
 
1542
    end;
 
1543
  end;
 
1544
  if InRemoveStayOnTopFlags > 0 then
 
1545
    dec(InRemoveStayOnTopFlags);}
 
1546
end;
 
1547
 
 
1548
function WndClassName(Wnd: HWND): String; inline;
 
1549
var
 
1550
  winClassName: array[0..19] of widechar;
 
1551
begin
 
1552
  GetClassName(Wnd, @winClassName, 20);
 
1553
  Result := winClassName;
 
1554
end;
 
1555
 
 
1556
function IsAlienWindow(Wnd: HWND): Boolean;
 
1557
 
 
1558
const
 
1559
  // list window class names is taken here:
 
1560
  // http://www.pocketpcdn.com/print/articles/?&atb.set(c_id)=51&atb.set(a_id)=7165&atb.perform(details)=
 
1561
  AlienWindowClasses: array[0..7] of String =
 
1562
  (
 
1563
    'menu_worker',        // can be also found by SHFindMenuBar
 
1564
    'MS_SOFTKEY_CE_1.0',  // google about that one. as I understand it related to bottom menu too
 
1565
    'Default Ime',
 
1566
    'Ime',
 
1567
    'static',
 
1568
    'OLEAUT32',
 
1569
    'FAKEIMEUI',
 
1570
    'tooltips_class32'
 
1571
  );
 
1572
 
 
1573
var
 
1574
  i: integer;
 
1575
  WndName: String;
 
1576
begin
 
1577
  WndName := WndClassName(Wnd);
 
1578
  Result := False;
 
1579
  for i := Low(AlienWindowClasses) to High(AlienWindowClasses) do
 
1580
    if WndName = AlienWindowClasses[i] then
 
1581
      Exit(True);
 
1582
end;
 
1583
 
 
1584
{procedure LogWindow(Window: HWND);
 
1585
begin
 
1586
  DbgAppendToFile(ExtractFilePath(ParamStr(0)) + '1.log',
 
1587
    'Window = ' + IntToStr(Window) + ' ClassName = ' + WndClassName(Window) + ' Thread id = ' + IntToStr(GetWindowThreadProcessId(Window, nil)));
 
1588
end;}
 
1589
 
 
1590
function MeasureText(const AWinControl: TWinControl; Text: string; var Width, Height: integer): boolean;
 
1591
var
 
1592
  textSize: Windows.SIZE;
 
1593
  winHandle: HWND;
 
1594
  canvasHandle: HDC;
 
1595
  oldFontHandle: HFONT;
 
1596
begin
 
1597
  winHandle := AWinControl.Handle;
 
1598
  canvasHandle := GetDC(winHandle);
 
1599
  oldFontHandle := SelectObject(canvasHandle, Windows.SendMessage(winHandle, WM_GetFont, 0, 0));
 
1600
  DeleteAmpersands(Text);
 
1601
 
 
1602
  Result := LCLIntf.GetTextExtentPoint32(canvasHandle, PChar(Text), Length(Text), textSize);
 
1603
 
 
1604
  if Result then
 
1605
  begin
 
1606
    Width := textSize.cx;
 
1607
    Height := textSize.cy;
 
1608
  end;
 
1609
  SelectObject(canvasHandle, oldFontHandle);
 
1610
  ReleaseDC(winHandle, canvasHandle);
 
1611
end;
 
1612
 
 
1613
function GetControlText(AHandle: HWND): string;
 
1614
var
 
1615
  TextLen: dword;
 
1616
  tmpWideStr: WideString;
 
1617
begin
 
1618
  TextLen := GetWindowTextLength(AHandle);
 
1619
  SetLength(tmpWideStr, TextLen+1);
 
1620
  GetWindowTextW(AHandle, PWideChar(tmpWideStr), TextLen + 1);
 
1621
  Result := UTF8Encode(tmpWideStr);
 
1622
end;
 
1623
 
 
1624
procedure WideStrCopy(Dest, Src: PWideChar);
 
1625
var
 
1626
  counter : longint;
 
1627
Begin
 
1628
  counter := 0;
 
1629
  while Src[counter] <> #0 do
 
1630
  begin
 
1631
    Dest[counter] := Src[counter];
 
1632
    Inc(counter);
 
1633
  end;
 
1634
  Dest[counter] := #0;
 
1635
end;
 
1636
 
 
1637
{ Exactly equal to StrLCopy but for PWideChars
 
1638
  Copyes a widestring up to a maximal length, in WideChars }
 
1639
function WideStrLCopy(dest, source: PWideChar; maxlen: SizeInt): PWideChar;
 
1640
var
 
1641
  counter: SizeInt;
 
1642
begin
 
1643
  counter := 0;
 
1644
 
 
1645
  while (Source[counter] <> #0)  and (counter < MaxLen) do
 
1646
  begin
 
1647
    Dest[counter] := Source[counter];
 
1648
    Inc(counter);
 
1649
  end;
 
1650
 
 
1651
  { terminate the string }
 
1652
  Dest[counter] := #0;
 
1653
  Result := Dest;
 
1654
end;
 
1655
 
 
1656
function WideStrCmp(W1, W2: PWideChar): Integer;
 
1657
var
 
1658
  counter: Integer;
 
1659
Begin
 
1660
  counter := 0;
 
1661
  While W1[counter] = W2[counter] do
 
1662
  Begin
 
1663
    if (W2[counter] = #0) or (W1[counter] = #0) then
 
1664
       break;
 
1665
    Inc(counter);
 
1666
  end;
 
1667
  Result := ord(W1[counter]) - ord(W2[counter]);
 
1668
end;
 
1669
 
 
1670
function GetWinCEPlatform: TApplicationType;
 
1671
{$ifdef MSWindows}
 
1672
begin
 
1673
  Result := atDesktop;
 
1674
end;
 
1675
{$else}
 
1676
var
 
1677
  buf: array[0..50] of WideChar;
 
1678
begin
 
1679
  Result := atDefault;
 
1680
 
 
1681
  if Windows.SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(buf), @buf, 0) then
 
1682
  begin
 
1683
    if WideStrCmp(@buf, 'PocketPC') = 0 then
 
1684
      Result := atPDA
 
1685
    else if WideStrCmp(@buf, 'SmartPhone') = 0 then
 
1686
      Result := atKeyPadDevice
 
1687
    else
 
1688
      // Other devices can set anything for the platform name,
 
1689
      // see http://bugs.freepascal.org/view.php?id=16615
 
1690
      // Here we just suppose that they are atDesktop
 
1691
      Result := atDesktop;
 
1692
  end
 
1693
  else if GetLastError = ERROR_ACCESS_DENIED then
 
1694
    Result := atKeyPadDevice
 
1695
  else
 
1696
    Result := atPDA;
 
1697
end;
 
1698
{$endif}
 
1699
 
 
1700
function IsHiResMode: Boolean;
 
1701
begin
 
1702
  {$ifdef MSWindows}
 
1703
  Result := False;
 
1704
  {$else}
 
1705
  Result := Screen.Width > 240;
 
1706
  {$endif}
 
1707
end;
 
1708
 
 
1709
 
 
1710
{-------------------------------------------------------------------------------
 
1711
  procedure AddToChangedMenus(Window: HWnd);
 
1712
 
 
1713
  Adds Window to the list of windows which need to redraw the main menu.
 
1714
-------------------------------------------------------------------------------}
 
1715
procedure AddToChangedMenus(Window: HWnd);
 
1716
begin
 
1717
  if ChangedMenus.IndexOf(Pointer(Window)) = -1 then // Window handle is not yet in the list
 
1718
    ChangedMenus.Add(Pointer(Window));
 
1719
end;
 
1720
 
 
1721
{------------------------------------------------------------------------------
 
1722
  Method: RedrawMenus
 
1723
  Params:  None
 
1724
  Returns: Nothing
 
1725
 
 
1726
  Redraws all changed menus
 
1727
 ------------------------------------------------------------------------------}
 
1728
procedure RedrawMenus;
 
1729
var
 
1730
  I: integer;
 
1731
begin
 
1732
  for I := 0 to  ChangedMenus.Count - 1 do
 
1733
    DrawMenuBar(HWND(ChangedMenus[I]));
 
1734
  ChangedMenus.Clear;
 
1735
end;
 
1736
 
 
1737
procedure UpdateWindowsVersion;
 
1738
{$ifdef WinCE}
 
1739
var
 
1740
  versionInfo: OSVERSIONINFO;
 
1741
begin
 
1742
  WindowsVersion := wince_other;
 
1743
 
 
1744
  System.FillChar(versionInfo, sizeof(OSVERSIONINFO), #0);
 
1745
  versionInfo.dwOSVersionInfoSize := sizeof(OSVERSIONINFO);
 
1746
 
 
1747
  if GetVersionEx(@versionInfo) then
 
1748
  begin
 
1749
    case versionInfo.dwMajorVersion of
 
1750
    1: WindowsVersion := wince_1;
 
1751
    2: WindowsVersion := Wince_2;
 
1752
    3: WindowsVersion := Wince_3;
 
1753
    4: WindowsVersion := Wince_4;
 
1754
    5:
 
1755
    begin
 
1756
      if versionInfo.dwMinorVersion = 2 then WindowsVersion := Wince_6
 
1757
      else WindowsVersion := Wince_5;
 
1758
    end;
 
1759
    6: WindowsVersion := Wince_6;
 
1760
    end;
 
1761
  end;
 
1762
end;
 
1763
{$else}
 
1764
begin
 
1765
  case Win32MajorVersion of
 
1766
    0..3:;
 
1767
    4: begin
 
1768
     if Win32Platform = VER_PLATFORM_WIN32_NT
 
1769
     then WindowsVersion := wvNT4
 
1770
     else
 
1771
       case Win32MinorVersion of
 
1772
         10: WindowsVersion := wv98;
 
1773
         90: WindowsVersion := wvME;
 
1774
       else
 
1775
         WindowsVersion :=wv95;
 
1776
       end;
 
1777
    end;
 
1778
    5: begin
 
1779
     case Win32MinorVersion of
 
1780
       0: WindowsVersion := wv2000;
 
1781
       1: WindowsVersion := wvXP;
 
1782
     else
 
1783
       // XP64 has also a 5.2 version
 
1784
       // we could detect that based on arch and versioninfo.Producttype
 
1785
       WindowsVersion := wvServer2003;
 
1786
     end;
 
1787
    end;
 
1788
    6: begin
 
1789
     case Win32MinorVersion of
 
1790
       0: WindowsVersion := wvVista;
 
1791
       1: WindowsVersion := wv7;
 
1792
     else
 
1793
       WindowsVersion := wvLater;
 
1794
     end;
 
1795
    end;
 
1796
  else
 
1797
    WindowsVersion := wvLater;
 
1798
  end;
 
1799
end;
 
1800
{$endif}
 
1801
 
 
1802
initialization
 
1803
  DefaultWindowInfo := TWindowInfo.Create;
 
1804
  WindowInfoAtom := Windows.GlobalAddAtom('WindowInfo');
 
1805
  ChangedMenus := TList.Create;
 
1806
  UpdateWindowsVersion();
 
1807
 
 
1808
finalization
 
1809
  Windows.GlobalDeleteAtom(WindowInfoAtom);
 
1810
  WindowInfoAtom := 0;
 
1811
  ChangedMenus.Free;
 
1812
end.