我需要一个内置的屏幕数字键盘在我的应用程序。由于各种原因,我不能使用TMS Software或其他商业组件产品。我对下面显示的基于按钮的解决方案感到非常满意,但是我还不知道如何解决焦点切换问题,点击按钮激活键盘窗体,我失去了我想要人物的焦点控制。我的解决方案如果将键盘按钮保留在目标表单中,但我希望独立于表单的解决方案。有没有一种方法来禁用按钮激活或知道焦点来自哪里,以便我可以使用像Scree.ActiveControl:= ??把它放回去?如何使用窗口焦点消息的Delphi屏幕上的键盘形式
回答
我不知道如何创建窗口的框架,它是不可聚焦的,当你点击它,所以下面的一个没有边框。正如Andreas所说,使用TSpeedButtons。
type
TKeypadForm = class(TForm)
SpeedButton1: TSpeedButton;
procedure SpeedButton1Click(Sender: TObject);
private
procedure CreateParams(var Params: TCreateParams); override;
procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE;
end;
procedure TKeypadForm.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := WS_POPUP or WS_THICKFRAME;
end;
procedure TKeypadForm.WMMouseActivate(var Message: TWMMouseActivate);
begin
Message.Result := MA_NOACTIVATE;
end;
procedure TKeypadForm.SpeedButton1Click(Sender: TObject);
begin
PostMessage(GetFocus, WM_KEYDOWN, VK_NUMPAD1, MakeLong(0, MapVirtualKey(VK_NUMPAD1, 0)));
end;
下面是如何显示的键盘窗口
procedure TForm18.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_RETURN: ShowWindow(KeypadForm.Handle, SW_SHOWNOACTIVATE);
VK_ESCAPE: ShowWindow(KeypadForm.Handle, SW_HIDE);
end;
end;
恕我直言,它不可能创建框架窗口的框架点击不聚焦窗口,从用户的角度来看,这将是相当混乱。 – 2011-05-06 13:35:35
谢谢,你是对的 - 鼠标消息是至关重要的,CreateParams不是这样。布莱恩。 – 2011-05-07 15:56:38
可以使用TSpeedButton在您的键盘此任务。 TSpeedButton没有对焦点进行加固。但形式确实如此。而且这很丑陋,即使你将注意力集中在主要形式上,焦点也会在两种形式之间闪烁。所以我会尝试创建一个没有焦点的表单。
一个名为WS_EX_NOACTIVATE的标志可以用来创建一个窗口(窗体),当用户单击它时它不会成为前景窗口。此外,当用户最小化或关闭前景窗口时,系统不会将此窗口置于前台。
要创建非激活的形式,覆盖的CreateParams方法:
procedure TMainForm.CreateParams(var Params: TCreateParams) ;
//const WS_EX_NOACTIVATE = $8000000;
begin
inherited;
Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE;
end;
当德尔福创建一个表单,创建方法调用是CreateWindowEx API函数来创建实际的窗口。
在执行CreateWindowEx之前,将调用CreateParams方法 - CreateParams允许您在创建窗口时根据特定需要更改窗口的默认样式。
但是窗户呢。 – 2011-05-06 11:13:26
好的,对。我增加了一个更好的答案... – Andreas 2011-05-06 11:38:10
仍然可以专注窗口。即使你将包括WM_MOUSEACTIVATE处理你的按钮将获得焦点。 – 2011-05-06 12:16:29
我的最终解决方案如下。这会创建一个带有边框的数字键盘,并且 - 如果边框被单击或调整大小,它会激活,但单击按钮不会从目标表单/控件中窃取焦点。简单地使用CreateParams并不适合我 - 它似乎需要WMMouseActivate消息。
我已经将它与一个例程相结合,我发现将操作系统的关键字发布到操作系统,而不仅仅是集中控制。请注意,下面的代码假定来自祖先形式的一些简单支持来设置默认大小和位置。感谢你的帮助。
unit UArtScreenKeyboardForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
UArtBaseForm, Buttons,
StdCtrls;
type
TArtScreenKeyboardForm = class(TArtBaseForm)
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE;
procedure FormResize(Sender: TObject);
private
{ Private declarations }
procedure DoOnbuttonClick(ASender: TObject);
procedure DrawButtons;
protected
procedure SetDefaultSizeAndPosition; override;
public
{ Public declarations }
end;
procedure ArtScreenKeyboardForm_Show;
procedure ArtScreenKeyboardForm_Hide;
implementation
{$R *.DFM}
uses
UArtLibrary;
type
TButtonKind = (
bk0,
bk1,
bk2,
bk3,
bk4,
bk5,
bk6,
bk7,
bk8,
bk9,
bkPlus,
bkMinus,
bkDel,
bkDiv,
bkMul,
bkEquals,
bkDecPt,
bkEnter);
const
ButtonCaptions : array[TButtonKind] of string = (
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'-',
'Back',
'/',
'*',
'=',
'.',
'Enter');
ScanCodes : array[TButtonKind] of cardinal = (
Ord('0'),
Ord('1'),
Ord('2'),
Ord('3'),
Ord('4'),
Ord('5'),
Ord('6'),
Ord('7'),
Ord('8'),
Ord('9'),
VK_ADD,
VK_SUBTRACT,
8, {BACKSPACE}
VK_DIVIDE,
VK_MULTIPLY,
Ord('='),
Ord('.'),
VK_RETURN);
var
ArtScreenKeyboardForm: TArtScreenKeyboardForm = nil;
procedure PostKeyEx32(key: Word; const shift: TShiftState; specialkey: Boolean) ;
{
Parameters :
* key : virtual keycode of the key to send. For printable keys this is simply the ANSI code (Ord(character)) .
* shift : state of the modifier keys. This is a set, so you can set several of these keys (shift, control, alt, mouse buttons) in tandem. The TShiftState type is declared in the Classes Unit.
* specialkey: normally this should be False. Set it to True to specify a key on the numeric keypad, for example.
Description:
Uses keybd_event to manufacture a series of key events matching the passed parameters. The events go to the control with focus. Note that for characters key is always the upper-case version of the character. Sending without any modifier keys will result in a lower-case character, sending it with [ ssShift ] will result in an upper-case character!
}
type
TShiftKeyInfo = record
shift: Byte ;
vkey: Byte ;
end;
ByteSet = set of 0..7 ;
const
shiftkeys: array [1..3] of TShiftKeyInfo =
((shift: Ord(ssCtrl) ; vkey: VK_CONTROL),
(shift: Ord(ssShift) ; vkey: VK_SHIFT),
(shift: Ord(ssAlt) ; vkey: VK_MENU)) ;
var
flag: DWORD;
bShift: ByteSet absolute shift;
j: Integer;
begin
for j := 1 to 3 do
begin
if shiftkeys[j].shift in bShift then
keybd_event(shiftkeys[j].vkey, MapVirtualKey(shiftkeys[j].vkey, 0), 0, 0) ;
end;
if specialkey then
flag := KEYEVENTF_EXTENDEDKEY
else
flag := 0;
keybd_event(key, MapvirtualKey(key, 0), flag, 0) ;
flag := flag or KEYEVENTF_KEYUP;
keybd_event(key, MapvirtualKey(key, 0), flag, 0) ;
for j := 3 downto 1 do
begin
if shiftkeys[j].shift in bShift then
keybd_event(shiftkeys[j].vkey, MapVirtualKey(shiftkeys[j].vkey, 0), KEYEVENTF_KEYUP, 0) ;
end;
end;
procedure TArtScreenKeyboardForm.DoOnbuttonClick(ASender: TObject);
var
Btn : TSpeedButton;
Kind : TButtonKind;
begin
Btn := ASender as TSpeedButton;
Kind := TButtonKind(StrToIntDef(Copy(Btn.Name, 4, MaxStrLen), 0));
PostKeyEx32(ScanCodes[Kind], [], False);
// As suggested also:
//PostMessage(GetFocus, WM_KEYDOWN, Ord('A'), 0);
// PostMessage(GetFocus, WM_KEYDOWN, VK_NUMPAD1, MakeLong(0, MapVirtualKey(VK_NUMPAD1, 0)));
end;
procedure TArtScreenKeyboardForm.WMMouseActivate(var Message: TWMMouseActivate);
begin
Message.Result := MA_NOACTIVATE;
end;
procedure ArtScreenKeyboardForm_Show;
begin
If ArtScreenKeyboardForm = nil then
begin
ArtScreenKeyboardForm := TArtScreenKeyboardForm.Create(Application);
ArtScreenKeyboardForm.Show;
end;
Application.ProcessMessages;
end;
procedure ArtScreenKeyboardForm_Hide;
begin
If ArtScreenKeyboardForm <> nil then
begin
ArtScreenKeyboardForm.Free;
ArtScreenKeyboardForm := nil;
end;
end;
procedure TArtScreenKeyboardForm.FormShow(Sender: TObject);
begin
DrawButtons;
end;
procedure TArtScreenKeyboardForm.SetDefaultSizeAndPosition;
begin
inherited;
Width := 300;
PlaceControl(Self, cpWorkAreaTopLeft);
end;
procedure TArtScreenKeyboardForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action := caFree;
ArtScreenKeyboardForm := nil;
end;
procedure TArtScreenKeyboardForm.FormCreate(Sender: TObject);
begin
Constraints.MinWidth := 200;
Constraints.MinHeight := (120 * 5) div 4;
end;
procedure TArtScreenKeyboardForm.DrawButtons;
procedure AddButton(ATop, ALeft, AWidth, AHeight : integer; AKind : TButtonKind);
function WidthPix(AValue : integer) : integer;
begin
Result := AValue * (ClientWidth div 4);
end;
function HeightPix(AValue : integer) : integer;
begin
Result := AValue * (ClientHeight div 5);
end;
var
Button : TSpeedButton;
begin
Button := TSpeedButton.Create(Self);
Button.Parent := Self;
Button.Left := WidthPix(ALeft);
Button.Top := HeightPix(ATop);
Button.Width := WidthPix(AWidth);
Button.Height := HeightPix(AHeight);
Button.Visible := True;
Button.Name := Format('btn%d', [Ord(AKind)]);
Button.Caption := ButtonCaptions[ AKind ];
button.OnClick := DoOnbuttonClick;
end;
var
I : integer;
begin
Height := (Width * 5) div 4;
ApplyScreenIconTitleFontToFont(Font);
Font.Size := Font.Size + ((Height-250) div 30);
Font.Style := Font.Style + [fsBold];
Font.Color := clGray;
For I := ComponentCount-1 downto 0 do
If Components[I] is TSpeedButton then
Components[I].Free;
Addbutton(0, 0, 1, 1, bkDel );
Addbutton(0, 1, 1, 1, bkEquals );
Addbutton(0, 2, 1, 1, bkDiv );
Addbutton(0, 3, 1, 1, bkMul );
Addbutton(1, 0, 1, 1, bk7 );
Addbutton(1, 1, 1, 1, bk8 );
Addbutton(1, 2, 1, 1, bk9 );
Addbutton(1, 3, 1, 1, bkMinus );
Addbutton(2, 0, 1, 1, bk4 );
Addbutton(2, 1, 1, 1, bk5 );
Addbutton(2, 2, 1, 1, bk6 );
Addbutton(2, 3, 1, 1, bkPlus );
Addbutton(3, 0, 1, 1, bk1 );
Addbutton(3, 1, 1, 1, bk2 );
Addbutton(3, 2, 1, 1, bk3 );
Addbutton(3, 3, 1, 2, bkEnter );
Addbutton(4, 0, 2, 1, bk0 );
Addbutton(4, 2, 1, 1, bkDecPt );
end;
procedure TArtScreenKeyboardForm.FormResize(Sender: TObject);
begin
DrawButtons;
end;
initialization
finalization
FreeAndNil(ArtScreenKeyboardForm);
end.
- 1. 如何使用键盘输入在屏幕上写入消息?
- 2. 如何使窗户始终如屏幕上的键盘
- 3. 当PasswordBox给定焦点时,软件键盘从屏幕消失
- 4. 定位子类UIAlertView中窗口,屏幕键盘上的iOS
- 5. 弹出窗口中的XAML TextBox在屏幕键盘上隐藏
- 6. 如何在屏幕上的键盘和按钮组之间移动焦点?
- 7. ipad屏幕键盘原点
- 8. 如何在wxWidgets中将键盘焦点设置为NULL窗口?
- 9. 如何监视当前哪个窗口具有键盘焦点
- 10. 在窗体上禁用屏幕键盘上的智能手机
- 11. 如何在Aurelia的屏幕键盘上使用?
- 12. 如何使键盘像Windows 7的屏幕键盘一样?
- 13. 键盘不在屏幕上
- 14. 屏幕键盘
- 15. 在屏幕上的键盘上打开
- 16. 如何在TextBox上取消键盘焦点
- 17. 防止JavaFx场景获得焦点 - 屏幕键盘
- 18. WinForms中的屏幕上的键盘
- 19. 如何强制没有标题栏的模态窗口的键盘焦点
- 20. 如何启用屏幕键盘?
- 21. 屏幕上(触摸屏)Web键盘
- 22. 如果用户点击屏幕键盘,我该如何解除键盘锁定?
- 23. 如何在Allegro的屏幕上键入键盘?
- 24. 屏幕上的键盘自动弹出
- 25. 屏幕键盘上的iPad webApps
- 26. Droid上的屏幕键盘问题
- 27. 屏幕键盘上的访问从windev
- 28. 屏幕键盘上的Windows IoT核心
- 29. 屏幕上对中窗口
- 30. 在屏幕键盘上使用正则表达式
要获取具有键盘焦点的窗口的句柄,请尝试使用[GetFocus](http://msdn.microsoft.com/zh-cn/library/ms646294%28v=vs.85%29.aspx ),但是如何创建不可聚焦的窗口我现在不能告诉你,但你可以获得灵感,例如从TRxCalcEdit,它有这样的弹出数字键盘。 – 2011-05-06 12:32:38