1{%MainUnit customdrawnint.pas}
2{******************************************************************************
3                  All CustomDrawn interface support routines
4                   Initial Revision  : Sat Jan 17 19:00:00 2004
5
6
7  !! Keep alphabetical !!
8
9 ******************************************************************************
10 Implementation
11 ******************************************************************************
12
13 *****************************************************************************
14  This file is part of the Lazarus Component Library (LCL)
15
16  See the file COPYING.modifiedLGPL.txt, included in this distribution,
17  for details about the license.
18 *****************************************************************************
19}
20
21//##apiwiz##sps##   // Do not remove
22
23(*
24
25function TQtWidgetSet.AddEventHandler(AHandle: THandle; AFlags: dword;
26  AEventHandler: TWaitHandleEvent; AData: PtrInt): PEventHandler;
27{
28  QSocketNotifier requires 1 notifier per event type
29  and doesn't provide userdata in the callback. We need to
30  make a map of socket -> userdata to store userdata
31  and also create 3 notifiers for each event. We also need to
32  use our own constants for the event types in the userland callback.
33  For simplicity same as GTK G_IO values are used here and
34  their ORs will be emulated. The callback will always only get
35  1 event tho.
36}
37
38  function CreateQt4NotifierRec(aNR: PWaitHandleEventHandler;
39           const aType: QSocketNotifierType; aCallback: QSocketNotifier_activated_Event): PWaitHandleEventHandler;
40  var
41    qsn: QSocketNotifierH;
42    qsn_hook: QSocketNotifier_hookH;
43    i: QSocketNotifierType;
44  begin
45    if aNR = nil then begin
46      Result := new(PWaitHandleEventHandler);
47      for i := QSocketNotifierRead to QSocketNotifierException do begin
48        Result^.qsn[i] := nil; // nil them so removeeventhandler can find out what to free
49        Result^.qsn_hook[i] := nil;
50      end;
51    end else
52      Result := aNR;
53
54    qsn := QSocketNotifier_create(aHandle, aType);
55    qsn_hook := QSocketNotifier_hook_create(qsn);
56    QSocketNotifier_hook_hook_activated(qsn_hook, aCallback); // todo: !!
57
58    Result^.qsn[aType] := qsn;
59    Result^.qsn_hook[aType] := qsn_hook;
60  end;
61
62begin
63  Result := nil;
64
65  if AFlags and (EVE_IO_READ or EVE_IO_WRITE or EVE_IO_ERROR) = 0 then
66    Exit; // no flag set, no dice
67
68  if AFlags and EVE_IO_READ = EVE_IO_READ then
69    Result := CreateQt4NotifierRec(Result, QSocketNotifierRead, @SocketNotifierRead_cb);
70
71  if AFlags and EVE_IO_WRITE = EVE_IO_WRITE then
72    Result := CreateQt4NotifierRec(Result, QSocketNotifierWrite, @SocketNotifierWrite_cb);
73
74  if AFlags and EVE_IO_ERROR = EVE_IO_ERROR then
75    Result := CreateQt4NotifierRec(Result, QSocketNotifierException, @SocketNotifierError_cb);
76
77  PWaitHandleEventHandler(Result)^.user_callback := AEventHandler;
78  PWaitHandleEventHandler(Result)^.udata := aData;
79  PWaitHandleEventHandler(Result)^.socket := AHandle;
80
81  if FSocketEventMap.HasId(aHandle) then begin // if we encounter this (shouldn't happen)
82    Debugln('TQtWidgetSet.AddEventHandler Duplicate handle: ' + IntToStr(aHandle));
83    FSocketEventMap.Delete(aHandle); // delete the previous one, potentially losing it..
84  end;
85  FSocketEventMap.Add(AHandle, Result);
86end;
87
88function TQtWidgetSet.AddPipeEventHandler(AHandle: THandle;
89  AEventHandler: TPipeEvent; AData: PtrInt): PPipeEventHandler;
90begin
91  // todo
92  Result := nil;
93end;
94
95function TQtWidgetSet.AddProcessEventHandler(AHandle: THandle;
96  AEventHandler: TChildExitEvent; AData: PtrInt): PProcessEventHandler;
97begin
98  // todo
99  Result := nil;
100end;*)
101
102{------------------------------------------------------------------------------
103  Function: CreateEmptyRegion
104  Params:
105  Returns: valid empty region
106 ------------------------------------------------------------------------------}
107function TCDWidgetSet.CreateEmptyRegion: hRGN;
108begin
109  Result:= HRGN(TLazRegion.Create());
110end;
111
112(*{------------------------------------------------------------------------------
113  Function: CreateStandardCursor
114  Params:
115  Returns:
116 ------------------------------------------------------------------------------}
117function TQtWidgetSet.CreateStandardCursor(ACursor: SmallInt): HCURSOR;
118var
119  CursorShape: QtCursorShape;
120begin
121  Result := 0;
122  if ACursor < crLow then Exit;
123  if ACursor > crHigh then Exit;
124
125  // TODO: map is better
126  case ACursor of
127    crNone      : CursorShape := QtBlankCursor;
128    crArrow     : CursorShape := QtArrowCursor;
129    crCross     : CursorShape := QtCrossCursor;
130    crIBeam     : CursorShape := QtIBeamCursor;
131    crSizeAll   : CursorShape := QtSizeAllCursor;
132    crSizeNESW  : CursorShape := QtSizeBDiagCursor;
133    crSizeNS    : CursorShape := QtSizeVerCursor;
134    crSizeNWSE  : CursorShape := QtSizeFDiagCursor;
135    crSizeWE    : CursorShape := QtSizeHorCursor;
136    crSizeNW    : CursorShape := QtSizeFDiagCursor;
137    crSizeN     : CursorShape := QtSizeVerCursor;
138    crSizeNE    : CursorShape := QtSizeBDiagCursor;
139    crSizeW     : CursorShape := QtSizeHorCursor;
140    crSizeE     : CursorShape := QtSizeHorCursor;
141    crSizeSW    : CursorShape := QtSizeBDiagCursor;
142    crSizeS     : CursorShape := QtSizeVerCursor;
143    crSizeSE    : CursorShape := QtSizeFDiagCursor;
144    crUpArrow   : CursorShape := QtUpArrowCursor;
145    crHourGlass : CursorShape := QtWaitCursor;
146    crHSplit    : CursorShape := QtSplitHCursor;
147    crVSplit    : CursorShape := QtSplitVCursor;
148    crNo        : CursorShape := QtForbiddenCursor;
149    crAppStart  : CursorShape := QtBusyCursor;
150    crHelp      : CursorShape := QtWhatsThisCursor;
151    crHandPoint : CursorShape := QtPointingHandCursor;
152  else
153    CursorShape := QtCursorShape(-1);
154  end;
155  if CursorShape <> QtCursorShape(-1) then
156    Result := HCURSOR(TQtCursor.Create(CursorShape));
157end;
158
159function TQtWidgetSet.CreateRubberBand(const ARect: TRect; const ABrush: HBrush): HWND;
160begin
161  // todo: think of ABrush
162  Result := HWND(QRubberBand_create(QRubberBandRectangle));
163  QRubberBand_setGeometry(QRubberBandH(Result), @ARect);
164  QWidget_show(QRubberBandH(Result));
165end;
166
167procedure TQtWidgetSet.DrawDefaultDockImage(AOldRect, ANewRect: TRect; AOperation: TDockImageOperation);
168begin
169  if FDockImage = nil then
170    FDockImage := QRubberBand_create(QRubberBandRectangle);
171
172  QRubberBand_setGeometry(FDockImage, @ANewRect);
173  case AOperation of
174    disShow: QWidget_show(FDockImage);
175    disHide: QWidget_hide(FDockImage);
176  end;
177end;
178
179procedure TQtWidgetSet.DrawGrid(DC: HDC; const R: TRect; DX, DY: Integer);
180var
181  QtDC: TQtDeviceContext absolute DC;
182  X, Y: Integer;
183  W, H: Integer;
184begin
185  if not IsValidDC(DC) then
186    exit;
187  QtDC.save;
188  try
189    W := (R.Right - R.Left - 1) div DX;
190    H := (R.Bottom - R.Top - 1) div DY;
191
192    for X := 0 to W do
193      for Y := 0 to H do
194        QtDC.drawPoint(R.Left + X * DX, R.Top + Y * DY + 1);
195  finally
196    QtDC.restore;
197  end;
198end;
199
200procedure TQtWidgetSet.DestroyRubberBand(ARubberBand: HWND);
201begin
202  QWidget_destroy(QRubberBandH(ARubberBand));
203end;
204
205{------------------------------------------------------------------------------
206  Function: FontIsMonoSpace
207  Params:
208  Returns:
209 ------------------------------------------------------------------------------}
210function TQtWidgetSet.FontIsMonoSpace(Font: HFont): Boolean;
211var
212  QtFontInfo: QFontInfoH;
213begin
214  Result := IsValidGDIObject(Font);
215  if Result then
216  begin
217    QtFontInfo := QFontInfo_create(TQtFont(Font).FHandle);
218    try
219  	  Result := QFontInfo_fixedPitch(QtFontInfo);
220    finally
221	    QFontInfo_destroy(QtFontInfo);
222    end;
223  end;
224end;*)
225
226function TCDWidgetSet.GetAvailableNativeCanvasTypes(DC: HDC; AAllowFallbackToParent: Boolean = False): TNativeCanvasTypes;
227begin
228  Result := [nctLazCanvas];
229end;
230
231function TCDWidgetSet.GetAvailableNativeHandleTypes(Handle: HWND; AAllowFallbackToParent: Boolean = False): TNativeHandleTypes;
232var
233  lBaseControl: TCDBaseControl absolute Handle;
234begin
235  Result := [];
236  {$ifdef CD_HasNativeFormHandle}
237  if Handle = 0 then Exit;
238  if (lBaseControl is TCDForm) or AAllowFallbackToParent then
239    Result := [CDBackendNativeHandle];
240  {$endif}
241end;
242
243(*function TQtWidgetSet.GetDesignerDC(WindowHandle: HWND): HDC;
244var
245  Widget: TQtWidget;
246begin
247  Widget := TQtWidget(WindowHandle);
248
249  if (Widget <> nil) and (Widget is TQtDesignWidget) then
250    Result := TQtDesignWidget(Widget).DesignContext
251  else
252    Result := 0;
253
254  if Result = 0 then
255    Result := GetDC(WindowHandle);
256end;*)
257
258function TCDWidgetSet.GetNativeCanvas(DC: HDC; AHandleType: TNativeCanvasType; AAllowFallbackToParent: Boolean = False): PtrInt;
259begin
260  Result := 0;
261  if AHandleType = nctLazCanvas then Result := PtrInt(DC);
262end;
263
264function TCDWidgetSet.GetNativeHandle(Handle: HWND; AHandleType: TNativeHandleType; AAllowFallbackToParent: Boolean = False): PtrInt;
265var
266  lBaseControl: TCDBaseControl absolute Handle;
267  lFormHandle: TCDForm;
268  lForm: TCustomForm;
269begin
270  Result := 0;
271  {$ifdef CD_HasNativeFormHandle}
272  if Handle = 0 then Exit;
273  if (lBaseControl is TCDForm) or AAllowFallbackToParent then
274  begin
275    if (lBaseControl is TCDWinControl) then
276    begin
277      lForm := Forms.GetParentForm((lBaseControl as TCDWinControl).WinControl);
278      if lForm = nil then Exit;
279      lFormHandle := TCDForm(lForm.Handle);
280    end
281    else
282      lFormHandle := TCDForm(lBaseControl);
283
284    if AHandleType = CDBackendNativeHandle then
285    begin
286      Result := lFormHandle.NativeHandle;
287    end;
288  end;
289  {$endif}
290end;
291
292(*function TQtWidgetSet.IsDesignerDC(WindowHandle: HWND; DC: HDC): Boolean;
293begin
294  Result := (WindowHandle <> 0) and (TQtWidget(WindowHandle) is TQtDesignWidget);
295  if Result then
296    Result := TQtDesignWidget(WindowHandle).DesignContext = DC;
297end;*)
298
299function TCDWidgetSet.IsScreenDC(ADC: HDC): Boolean;
300begin
301  Result := (ADC = HDC(Self.ScreenDC));
302end;
303
304function TCDWidgetSet.IsCDIntfControl(AWinControl: TObject): Boolean;
305begin
306  Result := IsIntfControl(TWinControl(AWinControl));
307end;
308
309function TCDWidgetSet.RadialPie(DC: HDC; x1, y1, x2, y2, Angle1, Angle2: Integer): Boolean;
310begin
311  Result := IsValidDC(DC);
312{  if Result then
313    QPainter_drawPie(TQtDeviceContext(DC).Widget, x1, y1, x2, y2, Angle1, Angle2);}
314end;
315
316{------------------------------------------------------------------------------
317  Function: RawImage_CreateBitmaps
318  Params: ARawImage:
319          ABitmap:
320          AMask:
321          ASkipMask: When set, no mask is created
322  Returns:
323
324  This functions is for TBitmap support
325
326  The memory allocation code was added because it is necessary for
327  TBitmap.LoadFromDevice support. For other operations it isnt needed
328
329  Make sure to copy the image into a new buffer here!!! If we just pass the memory
330  from our main TLazIntfImage then it will make a double release and corrupt the memory
331  See bug 21274
332 ------------------------------------------------------------------------------}
333function TCDWidgetSet.RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean;
334var
335  NewData, NewMaskData: PByte;
336  lRawImage: TRawImage;
337  lBitmap: TCDBitmap;
338begin
339  {$ifdef VerboseCDBitmap}
340  DebugLn(Format(':>[TCDWidgetSet.RawImage_CreateBitmaps] ARawImage.Description=%s', [ARawImage.Description.AsString]));
341  {$endif}
342
343  Result := False;
344  ABitmap := 0;
345  AMask := 0;
346  NewMaskData := nil;
347
348  // Copy the data (see bug 21274 as to why it is necessary)
349  if ARawImage.DataSize > 0 then
350  begin
351    NewData := AllocMem(ARawImage.DataSize);
352    System.Move(ARawImage.Data^, NewData^, ARawImage.DataSize);
353  end
354  else
355    NewData := nil;
356  {$ifdef VerboseCDBitmap}
357  DebugLn(Format(':[TCDWidgetSet.RawImage_CreateBitmaps] Data=%x Data size=%d NewData=%x',
358    [PtrUInt(ARawImage.Data), ARawImage.DataSize, PtrUInt(NewData)]));
359  {$endif}
360
361  // this is only a rough implementation, there is no check against bitsperpixel
362  lBitmap := TCDBitmap.Create;
363  ABitmap := HBITMAP(lBitmap);
364  System.Move(ARawImage, lRawImage, SizeOf(TRawImage));
365  lRawImage.Data := NewData;
366  lRawImage.Mask := nil;//Setting it to NewMaskData crashes
367  lRawImage.Palette := nil;
368  lBitmap.Image := TLazIntfImage.Create(lRawImage, True);
369  Result := ABitmap <> 0;
370
371  // Also create a bitmap for the mask
372  if (not ASkipMask) then
373  begin
374    // The Mask data
375    if (ARawImage.Mask <> nil) and (ARawImage.MaskSize > 0) then
376    begin
377      NewMaskData := GetMem(ARawImage.MaskSize);
378      System.Move(ARawImage.Mask^, NewMaskData^, ARawImage.MaskSize);
379    end
380    else
381      NewMaskData := nil;
382
383    lBitmap := TCDBitmap.Create;
384    AMask := HBITMAP(lBitmap);
385    lRawImage.Description.Init_BPP1(ARawImage.Description.Width, ARawImage.Description.Height);
386    lRawImage.Data := NewMaskData;
387    lRawImage.DataSize := ARawImage.MaskSize;
388    lRawImage.Mask := nil;
389    lRawImage.Palette := nil;
390    lBitmap.Image := TLazIntfImage.Create(lRawImage, True);
391  end;
392
393  {$ifdef VerboseCDBitmap}
394  DebugLn(Format(':<[TCDWidgetSet.RawImage_CreateBitmaps] out ABitmap=%x AMask=%x', [ABitmap, AMask]));
395  {$endif}
396end;
397
398{------------------------------------------------------------------------------
399  Function: RawImage_DescriptionFromBitmap
400  Params: ABitmap:
401          ADesc:
402  Returns:
403
404  Describes the inner format utilized by CustomDrawn + the specific information for this image
405 ------------------------------------------------------------------------------}
406function TCDWidgetSet.RawImage_DescriptionFromBitmap(ABitmap: HBITMAP; out ADesc: TRawImageDescription): Boolean;
407var
408  CDBitmap: TCDBitmap;
409  lRawImage: TRawImage;
410begin
411  {$ifdef VerboseCDBitmap}
412  DebugLn(Format('[TCDWidgetSet.RawImage_DescriptionFromBitmap] ABitmap=%x', [ABitmap]));
413  {$endif}
414
415  Result := IsValidBitmap(ABitmap);
416  if not Result then
417  begin
418    DebugLn('[RawImage_DescriptionFromBitmap] Invalid ABitmap');
419    Exit;
420  end;
421
422  CDBitmap := TCDBitmap(ABitmap);
423
424  CDBitmap.Image.GetRawImage(lRawImage);
425  ADesc := lRawImage.Description;
426end;
427
428{------------------------------------------------------------------------------
429  Function: RawImage_DescriptionFromDevice
430  Params: ADC:
431          ADesc:
432  Returns:
433 ------------------------------------------------------------------------------}
434function TCDWidgetSet.RawImage_DescriptionFromDevice(ADC: HDC; out ADesc: TRawImageDescription): Boolean;
435var
436  lSize: TPoint;
437begin
438  Result := true;
439
440  if ADC = 0 then
441  begin
442    GetDeviceSize(ADC, lSize);
443    ADesc.Init_BPP32_A8R8G8B8_BIO_TTB(lSize.X, lSize.Y);
444    Exit;
445  end;
446
447  ADesc := TLazIntfImage(TLazCanvas(ADC).Image).DataDescription;
448end;
449
450{------------------------------------------------------------------------------
451  Function: RawImage_FromBitmap
452  Params: ABitmap:
453          AMask:
454          ARect:
455          ARawImage:
456  Returns:
457
458  Creates a raw image from a bitmap
459 ------------------------------------------------------------------------------}
460function TCDWidgetSet.RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean;
461var
462  Desc: TRawImageDescription absolute ARawImage.Description;
463  CDBitmap: TCDBitmap;
464  lBmpRawImage: TRawImage;
465  NewData: PByte;
466  (*var
467    Image: TQtImage absolute ABitmap;
468    Mask: TQtImage absolute AMask;
469
470    WorkImage, WorkMask: TQtImage;
471    R: TRect;
472    Width, Height: Integer;
473    InvertPixels: Boolean;
474    Px: QRgb;*)
475begin
476  {$ifdef VerboseCDBitmap}
477  DebugLn(Format('[TCDWidgetSet.RawImage_FromBitmap] ABitmap=%x', [ABitmap]));
478  {$endif}
479
480  Result := IsValidBitmap(ABitmap);
481  if not Result then
482  begin
483    DebugLn('[RawImage_FromBitmap] Invalid ABitmap');
484    Exit;
485  end;
486
487  CDBitmap := TCDBitmap(ABitmap);
488
489  ARawImage.Init;
490  RawImage_DescriptionFromBitmap(ABitmap, Desc);
491
492  // Copy the data
493  CDBitmap.Image.GetRawImage(lBmpRawImage);
494  if lBmpRawImage.DataSize > 0 then
495  begin
496    NewData := AllocMem(lBmpRawImage.DataSize);
497    System.Move(lBmpRawImage.Data^, NewData^, lBmpRawImage.DataSize);
498  end
499  else
500    NewData := nil;
501
502  ARawImage.Data := NewData;
503  ARawImage.DataSize := lBmpRawImage.DataSize;
504
505(*  if ARect = nil
506  then begin
507    Width := Image.Width;
508    Height := Image.Height;
509    R := Rect(0, 0, Width, Height)
510  end
511  else begin
512    R := ARect^;
513    Width := R.Right - R.Left;
514    Height := R.Bottom - R.Top;
515  end;
516
517  if (Width = Image.Width) and (Height = Image.Height)
518  then begin
519    WorkImage := Image;
520    WorkMask := Mask;
521  end
522  else begin
523    WorkImage := TQtImage.Create;
524    WorkImage.CopyFrom(Image.FHandle, R.Left, R.Top, Width, Height);
525    if Mask <> nil then
526    begin
527      WorkMask := TQtImage.Create;
528      WorkMask.CopyFrom(Mask.FHandle, R.Left, R.Top, Width, Height);
529    end
530    else
531      WorkMask := nil;
532  end;
533
534  Desc.Width := WorkImage.width;
535  Desc.Height := WorkImage.height;
536
537  // copy data
538  ARawImage.DataSize := WorkImage.numBytes;
539  ReAllocMem(ARawImage.Data, ARawImage.DataSize);
540  if ARawImage.DataSize > 0 then
541    Move(WorkImage.bits^, ARawImage.Data^, ARawImage.DataSize);
542
543  if WorkMask <> nil then
544  begin
545    Desc.MaskLineEnd := rileDWordBoundary;
546    Desc.MaskBitOrder := riboReversedBits;
547    Desc.MaskBitsPerPixel := 1;
548    ARawImage.MaskSize := WorkMask.numBytes;
549    ReAllocMem(ARawImage.Mask, ARawImage.MaskSize);
550    if ARawImage.MaskSize > 0 then
551    begin
552      InvertPixels := False;
553      if WorkImage <> nil then
554      begin
555        Px := QImage_pixel(WorkImage.FHandle, 0, 0);
556        InvertPixels :=
557          not QImage_hasAlphaChannel(WorkMask.FHandle) and
558          not QImage_hasAlphaChannel(WorkImage.FHandle) and
559          // invert only if WorkImage is RGB32 fmt and allGray
560          (WorkImage.getFormat = QImageFormat_RGB32) and
561          QImage_allGray(WorkImage.FHandle) and
562          ((Px = 0) or (Px = $FF))
563      end;
564      if InvertPixels then
565        WorkMask.invertPixels(QImageInvertRGB);
566      Move(WorkMask.bits^, ARawImage.Mask^, ARawImage.MaskSize);
567      if InvertPixels then
568        WorkMask.invertPixels(QImageInvertRGB);
569    end;
570  end;
571
572  if WorkImage <> Image then
573    WorkImage.Free;
574  if WorkMask <> Mask then
575    WorkMask.Free;*)
576
577  Result := True;
578end;
579
580(*{------------------------------------------------------------------------------
581  Function: RawImage_FromDevice
582  Params: ADC:
583          ARect:
584          ARawImage:
585  Returns:
586
587  This function is utilized when the function TBitmap.LoadFromDevice is called
588
589  The main use for this function is to get a screenshot. It may have other uses,
590   but this is the only one implemented here.
591
592  MWE: exept for the desktop, there is always a bitmep selected in the DC.
593       So get this internal bitmap and pass it to RawImage_FromBitmap
594 ------------------------------------------------------------------------------}
595function TQtWidgetSet.RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean;
596var
597  Desc: TRawImageDescription absolute ARawImage.Description;
598
599  //SrcWidth, SrcHeight: Integer;
600  WinID: Cardinal;
601  DCSize: TSize;
602  Pixmap: TQtPixmap;
603  Image: QImageH;
604  Context: TQtDeviceContext;
605
606  procedure RawImage_FromImage(AImage: QImageH);
607  begin
608    ARawImage.DataSize := QImage_numBytes(AImage);
609    ARawImage.Data := GetMem(ARawImage.DataSize);
610    Move(QImage_bits(AImage)^, ARawImage.Data^, ARawImage.DataSize);
611    ARawImage.Mask := nil;
612  end;
613
614begin
615  {$ifdef VerboseQtWinAPI}
616    WriteLn('Trace:> [WinAPI GetRawImageFromDevice] SrcDC: ', dbghex(ADC),
617     ' SrcWidth: ', dbgs(ARect.Right - ARect.Left),
618     ' SrcHeight: ', dbgs(ARect.Bottom - ARect.Top));
619  {$endif}
620
621  // todo: copy only passed rectangle
622
623  Result := True;
624
625  ARawImage.Init;
626  FillStandardDescription(ARawImage.Description);
627  Context := TQtDeviceContext(ADC);
628
629  with DCSize, Context.getDeviceSize do
630  begin
631    cx := x;
632    cy := y;
633  end;
634
635  if Context.Parent <> nil then
636  begin
637    Pixmap := TQtPixmap.Create(@DCSize);
638    WinID := QWidget_winId(Context.Parent);
639    try
640      // if you have dual monitors then getDeviceSize return
641      // more width than screen width, but grabWindow will only grab one
642      // screen, so its width will be less
643      // Solution: we can either pass prefered size to grabWindow or
644      // correct Description size after. I see the first solution as more correct.
645      Pixmap.grabWindow(WinID, 0, 0, DCSize.cx, DCSize.cy);
646      Image := QImage_Create;
647      Pixmap.toImage(Image);
648      RawImage_FromImage(Image);
649      QImage_destroy(Image);
650    finally
651      Pixmap.Free;
652    end;
653  end else
654  begin
655    if Context.vImage <> nil then
656      RawImage_FromImage(Context.vImage.FHandle)
657    else
658    if Context.ParentPixmap <> nil then
659    begin
660      Image := QImage_create();
661      QPixmap_toImage(Context.ParentPixmap, Image);
662      RawImage_FromImage(Image);
663      QImage_destroy(Image);
664    end else
665      Result := False;
666  end;
667
668  // In this case we use the size of the context
669  Desc.Width := DCSize.cx;
670  Desc.Height := DCSize.cy;
671
672  {$ifdef VerboseQtWinAPI}
673    WriteLn('Trace:< [WinAPI GetRawImageFromDevice]');
674  {$endif}
675end;*)
676
677{------------------------------------------------------------------------------
678  Function: RawImage_QueryDescription
679  Params: AFlags:
680          ADesc:
681  Returns:
682 ------------------------------------------------------------------------------}
683function TCDWidgetSet.RawImage_QueryDescription(AFlags: TRawImageQueryFlags; var ADesc: TRawImageDescription): Boolean;
684begin
685  {$ifdef VerboseCDBitmap}
686  DebugLn(Format('[TCDWidgetSet.RawImage_QueryDescription] AFlags=%s', [RawImageQueryFlagsToString(AFlags)]));
687  {$endif}
688
689  // The default implementation is good enough, don't change this without a very good reason
690  Result := inherited RawImage_QueryDescription(AFlags, ADesc);
691end;
692
693(*function TQtWidgetSet.ReleaseDesignerDC(Window: HWND; DC: HDC): Integer;
694begin
695  Result := 1;
696end;
697
698procedure TQtWidgetSet.RemoveEventHandler(var AHandler: PEventHandler);
699var
700  wheh: PWaitHandleEventHandler;
701  i: QSocketNotifierType;
702begin
703  wheh := PWaitHandleEventHandler(aHandler);
704  FSocketEventMap.Delete(wheh^.socket); // delete from the map
705
706  for i := QSocketNotifierRead to QSocketNotifierException do
707    if Assigned(wheh^.qsn[i]) then begin
708      QSocketNotifier_destroy(wheh^.qsn[i]);
709      QSocketNotifier_hook_destroy(wheh^.qsn_hook[i]);
710    end;
711  dispose(wheh);
712  aHandler := nil;
713end;
714
715procedure TQtWidgetSet.RemovePipeEventHandler(var AHandler: PPipeEventHandler);
716begin
717  // todo
718end;
719
720procedure TQtWidgetSet.RemoveProcessEventHandler(var AHandler: PProcessEventHandler);
721begin
722  // todo
723end;
724
725procedure TQtWidgetSet.SetEventHandlerFlags(AHandler: PEventHandler;
726  NewFlags: dword);
727var
728  wheh: PWaitHandleEventHandler;
729  do_read: boolean;
730  do_write: boolean;
731  do_error: boolean;
732begin
733  wheh := PWaitHandleEventHandler(aHandler);
734
735  do_read := NewFlags and EVE_IO_READ = EVE_IO_READ;
736  do_write := NewFlags and EVE_IO_WRITE = EVE_IO_WRITE;
737  do_error := NewFlags and EVE_IO_ERROR = EVE_IO_ERROR;
738
739  QSocketNotifier_setEnabled(wheh^.qsn[QSocketNotifierRead], do_read);
740  QSocketNotifier_setEnabled(wheh^.qsn[QSocketNotifierWrite], do_write);
741  QSocketNotifier_setEnabled(wheh^.qsn[QSocketNotifierException], do_error);
742end;
743
744procedure TQtWidgetSet.SetRubberBandRect(const ARubberBand: HWND; const ARect: TRect);
745begin
746  QRubberBand_setGeometry(QRubberBandH(ARubberBand), @ARect);
747end;*)
748
749{$ifndef CD_HasNativeSelectItemDialog}
750function TCDWidgetset.ShowSelectItemDialog(const AItems: TStrings; APos: TPoint): Boolean;
751var
752  i: Integer;
753  lPopUpMenu: TPopUpMenu;
754  lCurItem: TMenuItem;
755begin
756  lPopUpMenu := TPopUpMenu.Create(nil);
757  for i := 0 to AItems.Count-1 do
758  begin
759    lCurItem := TMenuItem.Create(lPopUpMenu);
760    lPopUpMenu.Items.Add(lCurItem);
761    lCurItem.Caption := AItems[i];
762  end;
763  lPopUpMenu.OnClose := @HandleSelectItemDialogClose;
764  lPopUpMenu.PopUp(APos.X, APos.Y);
765  Result := True;
766end;
767
768procedure TCDWidgetset.HandleSelectItemDialogClose(ASender: TObject);
769begin
770  //ASender.Free; Crashes in X11 =( Fix me!!!
771end;
772
773{$endif}
774
775(*function TQtWidgetSet.TextUTF8Out(DC: HDC; X, Y: Integer; Str: PChar; Count: Longint): Boolean;
776begin
777  Result := False;
778  if IsValidDC(DC) then
779    Result := TextOut(DC, X, Y, Str, Count);
780end;*)
781
782//##apiwiz##eps##   // Do not remove, no wizard declaration after this line
783