win32: redo SpinEdit control:

- don't use CreateUpDownControl since it is deprecated for win32 (was made for 16bit win 3.1)
  - return Edit window handle as handle instead of UpDown

git-svn-id: trunk@25229 -
This commit is contained in:
paul 2010-05-07 02:47:44 +00:00
parent 07c85a5453
commit 8e045a3736
3 changed files with 128 additions and 128 deletions

View File

@ -45,7 +45,8 @@ Type
TWin32WindowInfo = record
AccelGroup: HACCEL;
Accel: HACCEL;
Overlay: HWND; // overlay, transparent window on top, used by designer
Overlay: HWND; // overlay, transparent window on top, used by designer
UpDown: HWND;
PopupMenu: TPopupMenu;
DefWndProc: WNDPROC;
ParentMsgHandler: TParentMsgHandlerProc;
@ -59,7 +60,6 @@ Type
isComboEdit: boolean; // is buddy of combobox, the edit control
isChildEdit: boolean; // is buddy edit of a control
isGroupBox: boolean; // is groupbox, and does not have themed tabpage as parent
askBuddyCoords: boolean; // ask buddy window about position and size
ThemedCustomDraw: boolean;// controls needs themed drawing in wm_notify/nm_customdraw
MaxLength: integer;
DrawItemIndex: integer; // in case of listbox, when handling WM_DRAWITEM
@ -753,21 +753,18 @@ end;
function LCLControlSizeNeedsUpdate(Sender: TWinControl;
SendSizeMsgOnDiff: boolean): boolean;
var
Window:HWND;
LMessage: TLMSize;
IntfWidth, IntfHeight: integer;
begin
Result:=false;
Window:= Sender.Handle;
LCLIntf.GetWindowSize(Window, IntfWidth, IntfHeight);
if (Sender.Width = IntfWidth)
and (Sender.Height = IntfHeight)
and (not Sender.ClientRectNeedsInterfaceUpdate) then
exit;
Result:=true;
if SendSizeMsgOnDiff then begin
Result := False;
LCLIntf.GetWindowSize(Sender.Handle, IntfWidth, IntfHeight);
if (Sender.Width = IntfWidth) and (Sender.Height = IntfHeight) and (not Sender.ClientRectNeedsInterfaceUpdate) then
Exit;
Result := True;
if SendSizeMsgOnDiff then
begin
//writeln('LCLBoundsNeedsUpdate B ',TheWinControl.Name,':',TheWinControl.ClassName,' Sending WM_SIZE');
Sender.InvalidateClientRectCache(true);
Sender.InvalidateClientRectCache(True);
// send message directly to LCL, some controls not subclassed -> message
// never reaches LCL
with LMessage do

View File

@ -2147,12 +2147,8 @@ var
R: TRect;
WindowPlacement: TWINDOWPLACEMENT;
ParentHandle: THandle;
WindowInfo: PWin32WindowInfo;
begin
Result := False;
WindowInfo := GetWin32WindowInfo(Handle);
if WindowInfo^.askBuddyCoords then
Handle := Windows.SendMessage(Handle, UDM_GETBUDDY, 0, 0);
if IsIconic(Handle) and GetWindowPlacement(Handle, @WindowPlacement) then
R := WindowPlacement.rcNormalPosition
@ -2193,14 +2189,12 @@ var
WindowInfo: PWin32WindowInfo;
Info: tagWINDOWINFO;
procedure AdjustForBuddySize;
procedure AdjustUpDownSize;
var
BuddyHandle: HWND;
BuddyWP: WINDOWPLACEMENT;
UpDownWP: WINDOWPLACEMENT;
begin
BuddyHandle := Windows.SendMessage(Handle, UDM_GETBUDDY, 0, 0);
if (BuddyHandle<>HWND(nil)) and Windows.GetWindowPlacement(BuddyHandle, BuddyWP) then
Width := WP.rcNormalPosition.Right - BuddyWP.rcNormalPosition.Left;
if Windows.GetWindowPlacement(WindowInfo^.UpDown, UpDownWP) then
Width := UpDownWP.rcNormalPosition.Right - WP.rcNormalPosition.Left;
end;
procedure ExcludeCaption; inline;
@ -2282,8 +2276,8 @@ begin
ExcludeCaption;
if WindowInfo^.askBuddyCoords then
AdjustForBuddySize;
if WindowInfo^.UpDown <> 0 then
AdjustUpDownSize;
end;
function TWin32WidgetSet.GradientFill(DC: HDC; Vertices: PTriVertex;

View File

@ -37,7 +37,7 @@ uses
CommCtrl, Windows, Win32Extra,
Spin, Controls, StdCtrls, LCLType, LCLProc, LMessages,
////////////////////////////////////////////////////
WSSpin, WSLCLClasses,
WSSpin, WSLCLClasses, WSProc,
Win32Int, Win32Proc, Win32WSStdCtrls, Win32WSControls;
type
@ -55,10 +55,10 @@ type
class procedure GetPreferredSize(const AWinControl: TWinControl;
var PreferredWidth, PreferredHeight: integer;
WithThemeSpace: Boolean); override;
class function GetSelStart(const ACustomEdit: TCustomEdit): integer; override;
class function GetSelLength(const ACustomEdit: TCustomEdit): integer; override;
class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; override;
class function GetValue(const ACustomFloatSpinEdit: TCustomFloatSpinEdit): Double; override;
class function GetSelStart(const ACustomEdit: TCustomEdit): integer; override;
class function GetSelLength(const ACustomEdit: TCustomEdit): integer; override;
class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; override;
class function GetValue(const ACustomFloatSpinEdit: TCustomFloatSpinEdit): Double; override;
class procedure SetReadOnly(const ACustomEdit: TCustomEdit; NewReadOnly: boolean); override;
class procedure SetSelStart(const ACustomEdit: TCustomEdit; NewStart: integer); override;
@ -80,60 +80,49 @@ uses
SysUtils;
{ TWin32WSCustomFloatSpinEdit }
function GetBuddyWindow(AHandle: HWND): HWND; inline;
begin
Result := SendMessage(AHandle, UDM_GETBUDDY, 0, 0)
end;
function SpinWindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
LParam: Windows.LParam): LResult; stdcall;
var
BuddyWindow: HWND;
begin
// before generic window proc
case Msg of
UDM_GETBUDDY:
Exit(CallDefaultWindowProc(Window, Msg, WParam, LParam));
WM_PAINT,
WM_PRINTCLIENT,
WM_ERASEBKGND:
begin
Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);
Exit;
end;
WM_DESTROY:
begin
BuddyWindow := GetBuddyWindow(Window);
DestroyWindow(BuddyWindow);
DestroyWindow(GetWin32WindowInfo(Window)^.UpDown);
end;
WM_ENABLE:
begin
BuddyWindow := GetBuddyWindow(Window);
Windows.EnableWindow(BuddyWindow, WParam <> 0);
Windows.EnableWindow(GetWin32WindowInfo(Window)^.UpDown, WParam <> 0);
end;
end;
Result := WindowProc(Window, Msg, WParam, LParam);
// after generic window proc
case Msg of
WM_SETFOCUS:
begin
BuddyWindow := GetBuddyWindow(Window);
Windows.SetFocus(BuddyWindow);
// don't select text in edit, if user clicked on the up down and the edit
// was already focused
if HWND(WPARAM)<>BuddyWindow then ;
// for LCL controls this is done in win32callback.inc
Windows.SendMessage(BuddyWindow, EM_SETSEL, 0, -1);
end;
end;
if Msg = WM_KILLFOCUS then
UpdateFloatSpinEditControl(Window, TCustomFloatSpinEdit(GetWin32WindowInfo(Window)^.WinControl));
end;
function SpinBuddyWindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
function SpinUpDownWndProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
LParam: Windows.LParam): LResult; stdcall;
var
AWindowInfo: PWin32WindowInfo;
begin
Result := WindowProc(Window, Msg, WParam, LParam);
if Msg = WM_KILLFOCUS then
begin
AWindowInfo := GetWin32WindowInfo(Window);
if AWindowInfo^.AWinControl is TCustomFloatSpinEdit then
UpdateFloatSpinEditControl(AWindowInfo^.AWinControl.Handle,
TCustomFloatSpinEdit(AWindowInfo^.AWinControl));
case Msg of
WM_PAINT,
WM_NCHITTEST,
WM_NCPAINT,
WM_NCCALCSIZE,
WM_PRINTCLIENT,
WM_ERASEBKGND:
begin
Result := CallDefaultWindowProc(Window, Msg, WParam, LParam);
Exit;
end;
end;
Result := WindowProc(Window, Msg, WParam, LParam);
end;
procedure UpdateFloatSpinEditControl(const Handle: HWND;
@ -152,18 +141,22 @@ end;
procedure UpdateFloatSpinEditText(const ASpinEdit: TCustomFloatSpinEdit;
const ANewValue: Double);
var
editHandle: HWND;
newValueText: string;
begin
editHandle := GetBuddyWindow(ASpinEdit.Handle);
newValueText := ASpinEdit.ValueToStr(ANewValue);
Windows.SendMessage(editHandle, WM_SETTEXT, 0, Windows.LPARAM(PChar(newValueText)));
Windows.SendMessage(ASpinEdit.Handle, WM_SETTEXT, 0, Windows.LPARAM(PChar(newValueText)));
end;
class function TWin32WSCustomFloatSpinEdit.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): HWND;
const
UDS_HOTTRACK = $0100;
UpDownHotStyle: array[Boolean] of DWORD = (0, UDS_HOTTRACK);
var
Params: TCreateWindowExParams;
HotTracking: BOOL;
UpDown: HWND;
Info: PWin32WindowInfo;
begin
// general initialization of Params
PrepareCreateWindow(AWinControl, AParams, Params);
@ -171,36 +164,49 @@ begin
with Params do
begin
SubClassWndProc := @SpinWindowProc;
if TCustomSpinEdit(AWinControl).BorderStyle = bsSingle then
FlagsEx := FlagsEx or WS_EX_CLIENTEDGE;
Flags := Flags or ES_AUTOHSCROLL;
HotTracking := False;
SystemParametersInfo(SPI_GETHOTTRACKING, 0, @HotTracking, 0);
{$IFDEF WindowsUnicodeSupport}
if UnicodeEnabledOS then
Buddy := CreateWindowExW(WS_EX_CLIENTEDGE, PWideChar(WideString(EditClsName)),
PWideChar(UTF8ToUTF16(StrCaption)), Flags or ES_AUTOHSCROLL,
Left, Top, Width, Height, Parent, HMENU(nil), HInstance, nil)
else
Buddy := CreateWindowEx(WS_EX_CLIENTEDGE, @EditClsName[0],
PChar(Utf8ToAnsi(StrCaption)), Flags or ES_AUTOHSCROLL,
begin
Window := CreateWindowExW(FlagsEx, PWideChar(WideString(EditClsName)),
PWideChar(UTF8ToUTF16(StrCaption)), Flags,
Left, Top, Width, Height, Parent, HMENU(nil), HInstance, nil);
UpDown := CreateWindowExW(0, UPDOWN_CLASSW, nil,
WS_CHILD or WS_VISIBLE or UDS_ALIGNRIGHT or UDS_ARROWKEYS or UpDownHotStyle[HotTracking],
CW_USEDEFAULT, CW_USEDEFAULT, 8, Height, Parent, HMENU(nil), HInstance, nil);
end
else
begin
Window := CreateWindowEx(FlagsEx, @EditClsName[0],
PChar(Utf8ToAnsi(StrCaption)), Flags,
Left, Top, Width, Height, Parent, HMENU(nil), HInstance, nil);
UpDown := CreateWindowExW(0, UPDOWN_CLASSA, nil,
WS_CHILD or WS_VISIBLE or UDS_ALIGNRIGHT or UDS_ARROWKEYS or UpDownHotStyle[HotTracking],
0, 0, 8, Height, Parent, HMENU(nil), HInstance, nil);
end;
{$ELSE}
Buddy := CreateWindowEx(WS_EX_CLIENTEDGE, @EditClsName[0], PChar(StrCaption),
Flags or ES_AUTOHSCROLL, Left, Top, Width, Height, Parent, HMENU(nil), HInstance, nil);
Window := CreateWindowEx(FlagsEx, @EditClsName[0], PChar(StrCaption),
Flags, Left, Top, Width, Height, Parent, HMENU(nil), HInstance, nil);
UpDown := CreateWindowExW(0, UPDOWN_CLASSW, nil,
WS_CHILD or WS_VISIBLE or UDS_ALIGNRIGHT or UDS_ARROWKEYS or UpDownHotStyle[HotTracking],
0, 0, 8, Height, Parent, HMENU(nil), HInstance, nil);
{$ENDIF}
Window := CreateUpDownControl(Flags or DWORD(WS_BORDER or UDS_ALIGNRIGHT or UDS_ARROWKEYS),
0, 0, // pos - ignored for buddy
0, 0, // size - ignored for buddy
Parent, 0, HInstance, Buddy,
1000, 0, 500);
Windows.SendMessage(UpDown, UDM_SETBUDDY, WPARAM(Window), 0);
end;
// create window
FinishCreateWindow(AWinControl, Params, true);
FinishCreateWindow(AWinControl, Params, True);
Info := GetWin32WindowInfo(Params.Window);
Info^.UpDown := UpDown;
UpdateFloatSpinEditControl(Params.Window, TCustomFloatSpinEdit(AWinControl));
// init buddy
Params.SubClassWndProc := @SpinBuddyWindowProc;
WindowCreateInitBuddy(AWinControl, Params);
Params.BuddyWindowInfo^.isChildEdit := True;
Params.WindowInfo^.askBuddyCoords := True;
// make possible LCL Wincontrol identification by Buddy handle
// TODO: should move to widget specific SetProp method
SetProp(Params.Buddy, 'WinControl', PtrUInt(AWinControl));
// init updown control
Info := AllocWindowInfo(UpDown);
Info^.AWinControl := AWinControl;
Info^.DefWndProc := Windows.WNDPROC(SetWindowLong(UpDown, GWL_WNDPROC, PtrInt(@SpinUpDownWndProc)));
SetProp(UpDown, 'WinControl', PtrUInt(AWinControl));
Result := Params.Window;
end;
@ -218,7 +224,7 @@ begin
if HIWORD(Message.WParam) = EN_CHANGE then
begin
lWindowInfo := GetWin32WindowInfo(AWinControl.Handle);
if lWindowInfo <> @DefaultWindowInfo then
if Assigned(lWindowInfo) and (lWindowInfo <> @DefaultWindowInfo) then
begin
SpinEdit := TCustomFloatSpinEdit(lWindowInfo^.WinControl);
lWindowInfo^.spinValue := SpinEdit.StrToValue(SpinEdit.Text);
@ -230,12 +236,12 @@ begin
if PNMHdr(Message.LParam)^.code = UDN_DELTAPOS then
begin
UpDownMsg := PNMUPDOWN(Message.LParam);
lWindowInfo := GetWin32WindowInfo(UpDownMsg^.hdr.hwndFrom);
lWindowInfo := GetWin32WindowInfo(AWinControl.Handle);
SpinEdit := TCustomFloatSpinEdit(lWindowInfo^.WinControl);
if not SpinEdit.ReadOnly then
begin
NewValue := SpinEdit.GetLimitedValue(
lWindowInfo^.spinValue + UpDownMsg^.iDelta * SpinEdit.Increment);
lWindowInfo^.spinValue - UpDownMsg^.iDelta * SpinEdit.Increment);
lWindowInfo^.spinValue := NewValue;
UpdateFloatSpinEditText(SpinEdit, NewValue);
@ -251,56 +257,61 @@ class procedure TWin32WSCustomFloatSpinEdit.GetPreferredSize(
const AWinControl: TWinControl; var PreferredWidth, PreferredHeight: integer;
WithThemeSpace: Boolean);
begin
if MeasureTextForWnd(GetBuddyWindow(AWinControl.Handle), 'Fj', PreferredWidth, PreferredHeight) then
{if MeasureTextForWnd(AWinControl.Handle, 'Fj', PreferredWidth, PreferredHeight) then
begin
PreferredWidth := 0;
Inc(PreferredHeight, 8);
end;
end;}
PreferredHeight := 0;
PreferredWidth := 0;
end;
class procedure TWin32WSCustomFloatSpinEdit.AdaptBounds(const AWinControl: TWinControl;
var Left, Top, Width, Height: integer; var SuppressMove: boolean);
var
WinHandle, BuddyHandle: HWND;
WinHandle, UpDown: HWND;
R: TRect;
WindowWidth: Integer;
UpDownWidth: Integer;
begin
WinHandle := AWinControl.Handle;
UpDown := GetWin32WindowInfo(WinHandle)^.UpDown;
{
// detach from buddy first
BuddyHandle := Windows.SendMessage(WinHandle, UDM_SETBUDDY, 0, 0);
MoveWindow(BuddyHandle, Left, Top, Width, Height, True);
Windows.SendMessage(UpDown, UDM_SETBUDDY, 0, 0);
MoveWindow(WinHandle, Left, Top, Width, Height, True);
// reattach
Windows.SendMessage(WinHandle, UDM_SETBUDDY, BuddyHandle, 0);
Windows.SendMessage(UpDown, UDM_SETBUDDY, WParam(WinHandle), 0);
}
BuddyHandle := GetBuddyWindow(WinHandle);
GetWindowRect(WinHandle, @R);
WindowWidth := R.Right - R.Left;
GetWindowRect(UpDown, @R);
UpDownWidth := R.Right - R.Left;
MoveWindow(BuddyHandle, Left, Top, Width - WindowWidth + 2, Height, True);
MoveWindow(WinHandle, Left + Width - WindowWidth, Top, WindowWidth, Height, True);
Windows.SetWindowPos(WinHandle, 0, Left, Top, Width - UpDownWidth + 2, Height,
SWP_NOZORDER or SWP_NOACTIVATE);
Windows.SetWindowPos(UpDown, 0, Left + Width - UpDownWidth, Top, UpDownWidth, Height,
SWP_NOZORDER or SWP_NOACTIVATE);
SuppressMove := True;
end;
class function TWin32WSCustomFloatSpinEdit.GetSelStart(const ACustomEdit: TCustomEdit): integer;
begin
Result := EditGetSelStart(GetBuddyWindow(ACustomEdit.Handle));
Result := EditGetSelStart(ACustomEdit.Handle);
end;
class function TWin32WSCustomFloatSpinEdit.GetSelLength(const ACustomEdit: TCustomEdit): integer;
begin
Result := EditGetSelLength(GetBuddyWindow(ACustomEdit.Handle));
Result := EditGetSelLength(ACustomEdit.Handle);
end;
class function TWin32WSCustomFloatSpinEdit.GetText(const AWinControl: TWinControl;
var AText: string): boolean;
begin
Result := AWinControl.HandleAllocated;
if not Result then
exit;
AText := GetControlText(GetBuddyWindow(AWinControl.Handle));
if not WSCheckHandleAllocated(AWinControl, 'GetText') then
Exit(False);
AText := GetControlText(AWinControl.Handle);
Result := True;
end;
class function TWin32WSCustomFloatSpinEdit.GetValue(
@ -312,20 +323,19 @@ end;
class procedure TWin32WSCustomFloatSpinEdit.SetReadOnly
(const ACustomEdit: TCustomEdit; NewReadOnly: boolean);
begin
Windows.SendMessage(GetBuddyWindow(ACustomEdit.Handle), EM_SETREADONLY,
Windows.WPARAM(NewReadOnly), 0);
Windows.SendMessage(ACustomEdit.Handle, EM_SETREADONLY, Windows.WPARAM(NewReadOnly), 0);
end;
class procedure TWin32WSCustomFloatSpinEdit.SetSelStart(const ACustomEdit: TCustomEdit;
NewStart: integer);
begin
EditSetSelStart(GetBuddyWindow(ACustomEdit.Handle), NewStart);
EditSetSelStart(ACustomEdit.Handle, NewStart);
end;
class procedure TWin32WSCustomFloatSpinEdit.SetSelLength(const ACustomEdit: TCustomEdit;
NewLength: integer);
begin
EditSetSelLength(GetBuddyWindow(ACustomEdit.Handle), NewLength);
EditSetSelLength(ACustomEdit.Handle, NewLength);
end;
class procedure TWin32WSCustomFloatSpinEdit.SetText(const AWinControl: TWinControl;
@ -333,24 +343,22 @@ class procedure TWin32WSCustomFloatSpinEdit.SetText(const AWinControl: TWinContr
begin
{$ifdef WindowsUnicodeSupport}
if UnicodeEnabledOS
then Windows.SetWindowTextW(GetBuddyWindow(AWinControl.Handle), PWideChar(UTF8ToUTF16(AText)))
else Windows.SetWindowText(GetBuddyWindow(AWinControl.Handle), PChar(Utf8ToAnsi(AText)));
then Windows.SetWindowTextW(AWinControl.Handle, PWideChar(UTF8ToUTF16(AText)))
else Windows.SetWindowText(AWinControl.Handle, PChar(Utf8ToAnsi(AText)));
{$else}
Windows.SetWindowText(GetBuddyWindow(AWinControl.Handle), PChar(AText));
Windows.SetWindowText(AWinControl.Handle, PChar(AText));
{$endif}
end;
class procedure TWin32WSCustomFloatSpinEdit.ShowHide(const AWinControl: TWinControl);
var
Buddy: HWND;
class procedure TWin32WSCustomFloatSpinEdit.ShowHide(
const AWinControl: TWinControl);
const
VisibilityToFlag: array[Boolean] of UINT = (SWP_HIDEWINDOW, SWP_SHOWWINDOW);
begin
// call inherited
TWin32WSWinControl.ShowHide(AWinControl);
Buddy := GetBuddyWindow(AWinControl.Handle);
if AWinControl.HandleObjectShouldBeVisible then
ShowWindow(Buddy, SW_SHOW)
else
ShowWindow(Buddy, SW_HIDE);
Windows.SetWindowPos(AWinControl.Handle, 0, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or VisibilityToFlag[AWinControl.HandleObjectShouldBeVisible]);
Windows.SetWindowPos(GetWin32WindowInfo(AWinControl.Handle)^.UpDown, 0, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or VisibilityToFlag[AWinControl.HandleObjectShouldBeVisible]);
end;
class procedure TWin32WSCustomFloatSpinEdit.UpdateControl(
@ -358,4 +366,5 @@ class procedure TWin32WSCustomFloatSpinEdit.UpdateControl(
begin
UpdateFloatSpinEditControl(ACustomFloatSpinEdit.Handle, ACustomFloatSpinEdit);
end;
end.