2011-05-06 2 views
8

내 응용 프로그램에 스크린 숫자 키패드가 내장되어 있어야합니다. 여러 가지 이유로 나는 TMS Software 또는 기타 상용 구성 요소 오퍼링을 사용할 수 없습니다. 아래에 표시된 버튼 기반 솔루션에 매우 만족하지만 포커스 스위치 문제를 해결하는 방법을 아직 볼 수 없습니다. 버튼을 클릭하면 키패드 양식이 활성화되고 문자를 원했던 초점을 잃게됩니다. 대상 폼 내에 키패드 단추를 유지하면 솔루션이 작동하지만 폼에 독립적 인 솔루션을 원합니다. 버튼 활성화를 비활성화하거나 포커스가 어디에서 왔는지 알고 있으므로 Scree.ActiveControl : = ??과 같은 것을 사용할 수 있습니까? 다시 넣으려고?델파이 온 - 스크린 키보드 양식에 대해 윈도우 포커스 메시지를 사용하는 방법

enter image description here

+0

키보드 포커스가있는 창을 처리하려면 [GetFocus] (http://msdn.microsoft.com/en-us/library/ms646294%28v=vs.85%29.aspx)를 사용해보십시오.), 그러나 unfocusable 창을 만드는 방법 나는 지금 당신을 말할 수는 없지만 영감을 얻을 수 있습니다. TRxCalcEdit에서 그런 종류의 팝업 숫자가 있습니다. –

답변

2

클릭 할 때 초점이 맞지 않는 프레임을 만드는 방법을 모르므로 다음 프레임은 테두리가 없습니다. 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; 
+0

그리고 IMHO 프레임을 클릭하여 윈도우를 포커스하지 않는 프레임 윈도우를 만드는 것은 불가능합니다. 이는 사용자 관점에서 보면 매우 혼란 스러울 것입니다. –

+0

고마워, 네가 옳았다. 마우스 메시지가 중요했고, CreateParams는 그렇게 중요하지 않았다. 브라이언. –

5

당신은 당신의 키패드에이 작업의 TSpeedButton을 사용할 수 있습니다. TSpeedButton은 초점을 강철하지 않습니다. 그러나 양식은 않습니다. 그리고 이것은 추한 것입니다, 비록 당신이 당신의 메인 폼으로 포커스를 되돌려도, 포커스는 두 폼 사이에서 깜박입니다. 그래서 나는 집중하지 않고 양식을 만들려고 노력할 것입니다.

WS_EX_NOACTIVATE라는 플래그를 사용하여 사용자가 클릭 할 때 전경 창이되지 않는 창 (양식)을 만들 수 있습니다. 또한 사용자가 전경 창을 최소화하거나 닫을 때이 창을 포 그라운드로 가져 오지 않습니다.

procedure TMainForm.CreateParams(var Params: TCreateParams) ; 
//const WS_EX_NOACTIVATE = $8000000; 
begin 
    inherited; 
    Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE; 
end; 

델파이 폼을 생성, 작성 방법은 실제 창을 만들 수있는 CreateWindowEx 함수 API 함수를 호출로

는 CreateParams을에게 방법을, 비 기동 양식을 만들 오버라이드 (override)합니다.

CreateWindowEx를 실행하기 전에 CreateParams 메서드가 호출됩니다. CreateParams를 사용하면 특정 요구에 맞게 창을 만들 때 기본 스타일을 변경할 수 있습니다.

+0

하지만 창은 않습니다. –

+0

좋습니다. 나는 더 나은 대답을 추가 ... – Andreas

+0

아직도 당신은 창문을 집중할 수 있습니다. WM_MOUSEACTIVATE 처리를 포함 시키더라도 버튼에 집중할 수 있습니다. –

0

내 최종 솔루션은 키패드 창을 표시하는 방법은 다음과 같습니다. 이것은 테두리가있는 숫자 패드를 만들고 - 예 - 테두리를 클릭하거나 크기를 조정했지만 버튼을 클릭해도 대상 양식/컨트롤에서 포커스를 훔치지 않으면 활성화됩니다. CreateParams를 사용하는 것만으로는 효과가 없었습니다. 대신 WMMouseActivate 메시지가 필요했습니다.

저는 집중된 컨트롤뿐만 아니라 OS에 키를 게시하는 루틴과 결합했습니다. 아래의 코드는 기본 크기와 위치를 설정하기위한 조상 양식의 간단한 지원을 전제로합니다. 모든 도움에 감사드립니다.

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. 
관련 문제