網站公告 :


Delphi K.Top討論區 » 會員作品發表區(限本人創作發表) » 螢幕數字鍵盤(含 Source)
發表新文章
 
主題:螢幕數字鍵盤(含 Source)
瀏覽次數:5208
dllee
站務副站長




發表:315
回覆:2470
積分:1695
註冊:2002-04-15

發送簡訊給我
#1 發表時間:2004-09-18 10:33:38 IP:211.76.xxx.xxx 未訂閱


主要參考及回應:
■【BCB】【問題】拖曳Form的問題
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55691

主要是因為 TitleBar 在移動時會看不到,不要 TitleBar
使用簡單自定的移動表單模式即可,不想下載可看以下的原始碼。
此工具對我來說,可用於筆記型電腦的使用者,因為筆記型電腦
的鍵盤都把數字鍵盤與其它按鍵結合在一起,而且每一台還都不一樣。
這個小工具預計會加入StatPlus2系統資源監測器
在以下的程式中,ImageList 只是為了模擬 [ X ] 按鈕可以像真的一樣,
在移動上去時變亮,移走變暗,如果不要這樣玩,程式可以更簡化一些。
另外,我會把表單預設隱藏在螢幕右邊,要用時再移出,用完就自動隱藏,
這樣就不會占空間。如果想把它移動螢幕左邊,只要按下表單不放,一直
拖到螢幕的左邊即可,如果要移回右邊也是一樣,不過在顯示時,它只會
顯示在最左邊或最右邊喔。
左上角的圖示,其說明文字目前 Active 視窗的 Title 可以讓您確認視窗。


//---------------------------------------------------------------------------
// ScreenKeyBoard (NumberPad) by Dong-Liang Lee http://dllee.ktop.com.tw
// <2004-09-18> 初版,自動隱藏到螢幕左邊或右邊,左上角圖示說明顯示目前
//        Active 的視窗名稱。
//        已知 BUG,只能按下數字鍵,不論是否 Number Locked。
//        主要用途:對於使用 NoteBook 的使用者因鍵盤濃縮,NumberPad
//        不易操作,使用此小工具,可以按需要的 NumberPad。
//        未來預計會加到 StatPlus2 之中。
//---------------------------------------------------------------------------

#include
#pragma hdrstop

#include "testKeyboardUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormKeyBoard *FormKeyBoard;
bool bMouseInForm;
bool bMouseInXButton;
bool bMouseDown;
int iDownX,iDownY;
bool bStickLeft;
HWND hwndLastActived=0;
//---------------------------------------------------------------------------
__fastcall TFormKeyBoard::TFormKeyBoard(TComponent* Owner)
    : TForm(Owner)
{
    Btn0->Tag=VK_NUMPAD0;
    Btn1->Tag=VK_NUMPAD1;
    Btn2->Tag=VK_NUMPAD2;
    Btn3->Tag=VK_NUMPAD3;
    Btn4->Tag=VK_NUMPAD4;
    Btn5->Tag=VK_NUMPAD5;
    Btn6->Tag=VK_NUMPAD6;
    Btn7->Tag=VK_NUMPAD7;
    Btn8->Tag=VK_NUMPAD8;
    Btn9->Tag=VK_NUMPAD9;
    BtnPlus->Tag=VK_ADD;
    BtnMinus->Tag=VK_SUBTRACT;
    BtnSlash->Tag=VK_DIVIDE;
    BtnStar->Tag=VK_MULTIPLY;
    BtnDot->Tag=VK_DECIMAL;
    BtnNumberLock->Tag=VK_NUMLOCK;
    BtnEnter->Tag=VK_RETURN;
    ImageList1->GetBitmap(2,ImgBtnClose->Picture->Bitmap);
    this->BorderStyle=bsNone;
    this->Width=103;
    this->Height=152;
    bStickLeft=true;
    bMouseInForm=true;
    DoubleBuffered=true;
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::FormCreate(TObject *Sender)
{ // http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55691
    long wsex=::GetWindowLongPtr(Handle,GWL_EXSTYLE);
    wsex |= WS_EX_NOACTIVATE;
    ::SetWindowLongPtr(Handle,GWL_EXSTYLE,wsex);
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::BtnClick(TObject *Sender)
{
    TButton *Btn=dynamic_cast(Sender);
    if(Btn==NULL)return;
    BYTE scancode = (BYTE)MapVirtualKey(Btn->Tag, 0);
    keybd_event(Btn->Tag,scancode,KEYEVENTF_EXTENDEDKEY|0,0);
    keybd_event(Btn->Tag,scancode,KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP,0);
    ImageList1->GetBitmap(2,ImgBtnClose->Picture->Bitmap);
    ImgBtnClose->Invalidate();
    SetWindowPos(this->Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::FormMouseDown(TObject *Sender, TMouseButton Button,
        TShiftState Shift, int X, int Y)
{
    bMouseDown=true;
    iDownX=X;
    iDownY=Y;
    SetWindowPos(this->Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::FormMouseUp(TObject *Sender, TMouseButton Button,
        TShiftState Shift, int X, int Y)
{
    bMouseDown=false;
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::FormMouseMove(TObject *Sender, TShiftState Shift,
        int X, int Y)
{
    if(bMouseInForm==false)
    {
    bMouseInForm=true;
    this->Color=clActiveCaption;
    if(bStickLeft) this->Left=Screen->Width-this->Width; // Show
    else        this->Left=0; // Show
    }
    if(bMouseInXButton==true)
    {
    bMouseInXButton=false;
    ImageList1->GetBitmap(2,ImgBtnClose->Picture->Bitmap);
    ImgBtnClose->Invalidate();
    }
    if(bMouseDown)
    {
    if(bStickLeft)
    {
        if(-X>Screen->Width*3/4)
        {
        bStickLeft=false;
        this->Left=0;
        }
    }
    else
    {
        if(X>Screen->Width*3/4)
        {
        bStickLeft=true;
        this->Left=Screen->Width-this->Width;
        }
    }
    // this->Left+=X-iDownX; // 因為我只想移動 Y 方向
    this->Top+=Y-iDownY;
    }
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::ImgBtnCloseClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::ImgBtnCloseMouseMove(TObject *Sender,
        TShiftState Shift, int X, int Y)
{
    if(bMouseInForm==false)
    {
    bMouseInForm=true;
    this->Color=clActiveCaption;
    if(bStickLeft) this->Left=Screen->Width-this->Width; // Show
    else        this->Left=0; // Show
    }
    if(bMouseInXButton==false)
    {
    bMouseInXButton=true;
    ImageList1->GetBitmap(1,ImgBtnClose->Picture->Bitmap);
    ImgBtnClose->Invalidate();
    }
}
//---------------------------------------------------------------------------
void __fastcall TFormKeyBoard::Timer1Timer(TObject *Sender)
{
    // Try to find the foreground windows
    // http://delphi.ktop.com.tw/topic.php?TOPIC_ID=37920 再改良一下
    HWND hwndThisActived=GetForegroundWindow();
    if(hwndLastActived!=hwndThisActived)
    {
    if(hwndThisActived==this->Handle)
    {
        hwndThisActived=hwndLastActived;
        if(hwndLastActived!=0)
        SetForegroundWindow(hwndLastActived);
    }
    SetWindowPos(this->Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
    hwndLastActived=hwndThisActived;

    char LastActivedTitle[256];
    GetWindowText(hwndLastActived,LastActivedTitle,256);
    this->Image1->Hint=AnsiString(LastActivedTitle);
    }

    if(bMouseDown==false && bMouseInForm==true)
    {
    POINT MousePos;
    if (GetCursorPos(&MousePos))
    {
        if(this->Left > MousePos.x
        || this->Top > MousePos.y
        || this->Left+this->Width < MousePos.x
        || this->Top+this->Height < MousePos.y)
        {
        bMouseInForm=false;
        this->Color=clNavy;//clInactiveCaption;
        if(bStickLeft) this->Left=Screen->Width-3; // Hide
        else        this->Left=3-this->Width; // Hide
        if(bMouseInXButton==true)
        {
        bMouseInXButton=false;
        ImageList1->GetBitmap(2,ImgBtnClose->Picture->Bitmap);
        ImgBtnClose->Invalidate();
        }
        }
    }
    }
}
//---------------------------------------------------------------------------



吃軟也吃硬 dllee.ktop.com.tw 視動科技 VMASK - ViewMove Automation Software Kernel
------
http://blog.yam.com/dllee/

附加檔案:56498_testKeyboard.zip

bigdogchina
版主




發表:238
回覆:523
積分:302
註冊:2003-04-28

發送簡訊給我
#2 發表時間:2004-09-18 11:24:49 IP:211.162.xxx.xxx 未訂閱

厲害,厲害,萬分敬仰!!!


=================================
人生在勤,不索何獲
業精於勤荒於嬉,行成於思毀於隨
臨淵羡魚不如退而結網

------
人生在勤,不索何获?

dllee
站務副站長




發表:315
回覆:2470
積分:1695
註冊:2002-04-15

發送簡訊給我
#3 發表時間:2004-09-21 08:19:02 IP:211.76.xxx.xxx 未訂閱

conundrum 大大所貼的:
■【轉貼】螢幕軟鍵盤
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=56391
不是使用 WS_EX_NOACTIVATE
用的是 AttachThreadInput() 這個 API,改天再來改寫一個吧


StatPlus 系統資源監測器(on SoftKing) 視動科技 VMASK - ViewMove Automation Software Kernel

------
http://blog.yam.com/dllee/

conundrum
尊榮會員




發表:893
回覆:1272
積分:628
註冊:2004-01-06

發送簡訊給我
#4 發表時間:2004-09-21 18:56:48 IP:61.221.xxx.xxx 未訂閱

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/attachthreadinput.asp
AttachThreadInput

The AttachThreadInput function attaches or detaches the input processing mechanism of one thread to that of another thread.


BOOL AttachThreadInput(
    DWORD idAttach,
    DWORD idAttachTo,
    BOOL fAttach
);

Parameters
idAttach
[in] Identifier of the thread to be attached to another thread. The thread to be attached cannot be a system thread.
idAttachTo
[in] Identifier of the thread to which idAttach will be attached. This thread cannot be a system thread.
A thread cannot attach to itself. Therefore, idAttachTo cannot equal idAttach.

fAttach
[in] If this parameter is TRUE, the two threads are attached. If the parameter is FALSE, the threads are detached.
Return Values
If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. There is no extended error information; do not call GetLastError.

Remarks
Windows created in different threads typically process input independently of each other. That is, they have their own input states (focus, active, capture windows, key state, queue status, and so on), and they are not synchronized with the input processing of other threads. By using the AttachThreadInput function, a thread can attach its input processing to another thread. This also allows threads to share their input states, so they can call the SetFocus function to set the keyboard focus to a window of a different thread. This also allows threads to get key-state information. These capabilities are not generally possible.

The AttachThreadInput function fails if either of the specified threads does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the USER or GDI functions. The AttachThreadInput function also fails if a journal record hook is installed. Journal record hooks attach all input queues together.

Note that key state, which can be ascertained by calls to the GetKeyState or GetKeyboardState function, is reset after a call to AttachThreadInput. You cannot attach a thread to a thread in another desktop.

Requirements
Client: Requires Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98, or Windows 95.
Server: Requires Windows Server 2003, Windows 2000 Server, or Windows NT Server.
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib.


See Also
Processes and Threads Overview, Process and Thread Functions, GetCurrentThreadId, GetKeyState, GetKeyboardState, GetWindowThreadProcessId, SetFocus


報告 dllee 利害 期待
小鍵盤 再現江湖 哈哈



發表人 - conundrum 於 2004/09/21 18:59:30


dllee
站務副站長




發表:315
回覆:2470
積分:1695
註冊:2002-04-15

發送簡訊給我
#5 發表時間:2004-09-22 09:33:27 IP:220.139.xxx.xxx 未訂閱

M$ 的 OSK 沒有使用 WS_EX_NOACTIVATE (由其 Windows 的狀態可知)
也沒有使用 AttachThreadInput() (由其 Import Function List 可知)
而是使用其他的方式。


StatPlus 系統資源監測器 @ SoftKing 視動科技 VMASK - ViewMove Automation Software Kernel

------
http://blog.yam.com/dllee/

teddywolf
一般會員




發表:0
回覆:1
積分:0
註冊:2004-09-24

發送簡訊給我
#6 發表時間:2004-09-24 14:52:29 IP:210.21.xxx.xxx 未訂閱

dlllee的程序在win 2K以上工作正常。
但在win98下會有失去焦點的問題。
在98中你嘗試在資源管理器(繁体WIN中的名字應該是:檔案總管)
中修改文件名,點擊數字鍵盤將使資源管理器失去焦點。
用AttachThreadInput()做的VC的程序也有同樣的問題。

實際上在WIN2K以上的系統,只要添加了屬性WS_EX_NOACTIVATE就可以
解決焦點丟失問題。
但在98下,這個問題該如何解決,有人研究過嗎?

我這里有一個程序是用DELPHI寫的soft_keyboard,可惜沒有源碼,
在WIN98,WIN2K下都可以正常工作。請告訴我如何上傳這個例子。


sanujp00
一般會員




發表:0
回覆:1
積分:0
註冊:2009-03-19

發送簡訊給我
#7 發表時間:2009-03-19 16:28:46 IP:203.75.xxx.xxx 訂閱

我把他改成 Delphi ,真的很好用
============================


unit TestKeyboardUnit;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ImgList, ExtCtrls, StdCtrls;
type
  TFormKeyBoard = class(TForm)
    Image1: TImage;
    ImgBtnClose: TImage;
    BtnNumberLock: TButton;
    BtnSlash: TButton;
    BtnStar: TButton;
    BtnMinus: TButton;
    Btn9: TButton;
    BtnPlus: TButton;
    Btn8: TButton;
    Btn7: TButton;
    Btn4: TButton;
    Btn5: TButton;
    Btn6: TButton;
    Btn3: TButton;
    Btn2: TButton;
    Btn1: TButton;
    Btn0: TButton;
    BtnDot: TButton;
    BtnEnter: TButton;
    Timer1: TTimer;
    ImageList1: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure BtnNumberLockClick(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImgBtnCloseClick(Sender: TObject);
    procedure ImgBtnCloseMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  FormKeyBoard: TFormKeyBoard;
  bMouseInForm:Boolean;
  bMouseInXButton:Boolean;
  bMouseDown:Boolean;
  iDownX,iDownY:Integer;
  bStickLeft:Boolean;
  hwndLastActived : THandle;
implementation
{$R *.dfm}
procedure TFormKeyBoard.FormCreate(Sender: TObject);
var wsex:Longint;
begin
  Btn0.Tag          := VK_NUMPAD0;
  Btn1.Tag          := VK_NUMPAD1;
  Btn2.Tag          := VK_NUMPAD2;
  Btn3.Tag          := VK_NUMPAD3;
  Btn4.Tag          := VK_NUMPAD4;
  Btn5.Tag          := VK_NUMPAD5;
  Btn6.Tag          := VK_NUMPAD6;
  Btn7.Tag          := VK_NUMPAD7;
  Btn8.Tag          := VK_NUMPAD8;
  Btn9.Tag          := VK_NUMPAD9;
  BtnPlus.Tag       := VK_ADD;
  BtnMinus.Tag      := VK_SUBTRACT;
  BtnSlash.Tag      := VK_DIVIDE;
  BtnStar.Tag       := VK_MULTIPLY;
  BtnDot.Tag        := VK_DECIMAL;
  BtnNumberLock.Tag := VK_NUMLOCK;
  BtnEnter.Tag      := VK_RETURN;
  ImageList1.GetBitmap(2,ImgBtnClose.Picture.Bitmap);
  self.BorderStyle:=bsNone;
//  self.Width:=103;
//  self.Height:=152;
  bStickLeft:=true;
  bMouseInForm:=true;
  DoubleBuffered:=true;
//======================================================
//  wsex :=GetWindowLongPtr(Self.Handle,GWL_EXSTYLE);
  wsex :=GetWindowLong(Self.Handle,GWL_EXSTYLE);
  wsex := wsex OR WS_EX_NOACTIVATE;
//  SetWindowLongPtr(Self.Handle,GWL_EXSTYLE,wsex);
  SetWindowLong(Self.Handle,GWL_EXSTYLE,wsex);
end;
 

procedure TFormKeyBoard.BtnNumberLockClick(Sender: TObject);
var Btn:TButton;
    scancode:BYTE;
begin
  Btn:=(Sender as TButton); //dynamic_cast(Sender);
  if(Btn=NIL) then exit;
  scancode := BYTE( MapVirtualKey(Btn.Tag, 0) );
  keybd_event(Btn.Tag, scancode, KEYEVENTF_EXTENDEDKEY OR 0, 0);
  keybd_event(Btn.Tag, scancode, KEYEVENTF_EXTENDEDKEY OR KEYEVENTF_KEYUP, 0);
  ImageList1.GetBitmap(2, ImgBtnClose.Picture.Bitmap);
  ImgBtnClose.Invalidate();
  SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
end;
procedure TFormKeyBoard.FormMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  bMouseDown:=true;
  iDownX:=X;
  iDownY:=Y;
  SetWindowPos(self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
end;

procedure TFormKeyBoard.FormMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if(bMouseInForm=false) then
  begin
    bMouseInForm:=true;
    self.Color:=clActiveCaption;
    if(bStickLeft)
      then self.Left:=Screen.Width-self.Width // Show
      else self.Left:=0; // Show
  end;
  if(bMouseInXButton=true) then
  begin
    bMouseInXButton:=false;
    ImageList1.GetBitmap(2,ImgBtnClose.Picture.Bitmap);
    ImgBtnClose.Invalidate();
  end;
  if(bMouseDown)then
  begin
    if(bStickLeft) then
    begin
      if(-X>Screen.Width*3/4) then
      begin
        bStickLeft:=false;
        self.Left:=0;
      end;
    end else begin
      if(X > Screen.Width*3/4) then
      begin
        bStickLeft:=true;
        self.Left:=Screen.Width - self.Width;
      end;
    end;
    // this->Left+=X-iDownX;  // 因為我只想移動 Y 方向
    self.Top:=self.Top + Y - iDownY;
  end;
end;
procedure TFormKeyBoard.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  bMouseDown:=false;
end;
procedure TFormKeyBoard.ImgBtnCloseClick(Sender: TObject);
begin
   Close;
end;
procedure TFormKeyBoard.ImgBtnCloseMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
  if(bMouseInForm=false) then
  begin
    bMouseInForm:=true;
    self.Color:=clActiveCaption;
    if(bStickLeft)
      then self.Left:=Screen.Width-self.Width // Show
      else self.Left:=0; // Show
  end;
  if(bMouseInXButton=false) then
  begin
    bMouseInXButton:=true;
    ImageList1.GetBitmap(1,ImgBtnClose.Picture.Bitmap);
    ImgBtnClose.Invalidate();
  end;
end;
procedure TFormKeyBoard.Timer1Timer(Sender: TObject);
var hwndThisActived:THandle;
    LastActivedTitle:array[0..255]of char;
    MousePos:TPOINT;
begin
  // Try to find the foreground windows
  hwndThisActived:=GetForegroundWindow();
  if(hwndLastActived<>hwndThisActived) then
  begin
    if(hwndThisActived=self.Handle) then
    begin
      hwndThisActived:=hwndLastActived;
      if(hwndLastActived<>0) then
        SetForegroundWindow(hwndLastActived);
    end;
    SetWindowPos(self.Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);
    hwndLastActived:=hwndThisActived;

    GetWindowText(hwndLastActived,LastActivedTitle,256);
    self.Image1.Hint:=AnsiString(LastActivedTitle);
  end;
  if( (bMouseDown=false) and (bMouseInForm=true) ) then
  begin
    if ( GetCursorPos(MousePos) ) then
    begin
      if( (self.Left > MousePos.x)or
          (self.Top > MousePos.y) or
          ((self.Left+self.Width) < MousePos.x) or
          ((self.Top+self.Height) < MousePos.y) ) then
      begin
        bMouseInForm:=false;
        self.Color:=clNavy;//clInactiveCaption;
        if(bStickLeft)
        then self.Left:=Screen.Width-3 // Hide
        else self.Left:=3-self.Width; // Hide
        if(bMouseInXButton=true) then
        begin
          bMouseInXButton:=false;
          ImageList1.GetBitmap(2,ImgBtnClose.Picture.Bitmap);
          ImgBtnClose.Invalidate();
        end;
      end;
    end;
  end;
end;
end.


系統時間:2010-09-03 19:07:13,  線上使用者 262 / Max 3,401,主題數:92,416,回覆數:208,133。  聯絡我們 | Delphi.ktop討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!

趴趴狗旅遊網大花蓮旅遊網大花蓮民宿網花蓮市旅遊網花蓮市民宿網大南投旅遊網大南投民宿網
日月潭風景區日月潭旅遊網日月潭民宿網台東旅遊網台東民宿網集集旅遊網集集民宿網
關子嶺旅遊網關子嶺民宿網白河旅遊網白河民宿網
. . . . . . . .