⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keywindow.pas

📁 delphi写的屏幕键盘
💻 PAS
字号:
unit KeyWindow;

interface

uses Windows;

function RegisterKeys(): Bool;
function CreateKeys(hMainWnd: HWnd): Bool;
function ReSizeKeys(ColMargin, RowMargin: Single): Bool;
function LocateKey(hKeyWnd: HWnd): Integer;
function GetKeyLong(nIndex: Integer): Integer;
function SetKeyLong(nIndex, nState: Integer): Bool;
function RedrawKeys(): Bool;
function RedrawNumLock(): Bool;
function RedrawCapsLock(): Bool;
function RedrawScrollLock(): Bool;

implementation

uses Messages, KbFunc, KbUsEx, KbSend, Setting, ResDef;

//
// 按键窗口句柄
//
var KeyWndList: array[0..103] of HWnd;

//
// ** 前置声明 **
//
function SetKeyRegion(hKeyWnd: HWnd; Width, Height: Integer): Bool; forward;
function KeyWndProc(hKeyWnd: HWnd; uMsg: UInt; wParam: WParam; lParam: LParam): LResult; stdcall; forward;
function DrawKeyRed(hKeyDc: HDC; Rect: TRect): Bool; forward;
function DrawKeyIcon(hKeyDc: HDC; pIconName: PChar; Rect: TRect): Bool; forward;
function DrawKeyBmp(hKeyDc: HDC; pBmpName: PChar; Rect: TRect): Bool; forward;
function DrawKeyText(hKeyDc: HDC; Rect: TRect; nIndex, nState: Integer): Bool; forward;
function DrawKeyLight(hKeyDc: HDC; Rect: TRect): Bool; forward;

//
// 注册按键窗口
//
function RegisterKeys(): Bool;
var
  WndClass: TWndClass;
  StrClass: array[0..20] of Char;
  J: Integer;
begin
  Result := False;

  WndClass.style         := CS_HREDRAW or CS_VREDRAW;
  WndClass.lpfnWndProc   := @KeyWndProc;
  WndClass.cbClsExtra    := 0;
  WndClass.cbWndExtra    := SizeOf(DWord); // 按键状态 ( 0 = 正常, 1 = 显亮, 2 = 按下 )
  WndClass.hInstance     := HInstance;
  WndClass.hIcon         := 0;
  WndClass.hCursor       := LoadCursor(HInstance, MakeIntResource(IDC_CURHAND));
  WndClass.hbrBackground := 0;
  WndClass.lpszMenuName  := nil;
  WndClass.lpszClassName := @StrClass;

  // All keys class
  for J := Low(KbKeyList) to High(KbKeyList) do
  begin
    case (KbKeyList[J].kType) of
      KNORMAL_TYPE:
      begin
        wvsprintf(StrClass, 'N%d_Mz', @J);
        WndClass.hbrBackground := COLOR_WINDOW + 1;
      end;

      KMODIFIER_TYPE:
      begin
        wvsprintf(StrClass, 'M%d_Mz', @J);
        WndClass.hbrBackground := COLOR_MENU + 1;
      end;

      KDEAD_TYPE:
      begin
        wvsprintf(StrClass, 'D%d_Mz', @J);
        WndClass.hbrBackground := COLOR_MENU + 1;
      end;

      NUMLOCK_TYPE:
      begin
        wvsprintf(StrClass, 'NL%d_Mz', @J);
        WndClass.hbrBackground := COLOR_MENU + 1;
      end;

      SCROLLOCK_TYPE:
      begin
        wvsprintf(StrClass, 'SL%d_Mz', @J);
        WndClass.hbrBackground := COLOR_MENU + 1;
      end;

      CAPSLOCK_TYPE:
      begin
        wvsprintf(StrClass, 'CL%d_Mz', @J);
        WndClass.hbrBackground := COLOR_MENU + 1;
      end;

      else Exit; // **
    end;

    if (RegisterClass(WndClass) = 0) then Exit;
  end;

  Result := True;
end;

//
// 建立按键窗口
//
function CreateKeys(hMainWnd: HWnd): Bool;
var
  StrClass: array[0..20] of Char;
  J: Integer;
begin
  Result := False;

  for J := Low(KbKeyList) to High(KbKeyList) do
  begin
    case (KbKeyList[J].kType) of
      KNORMAL_TYPE:
        wvsprintf(StrClass, 'N%d_Mz', @J);

      KMODIFIER_TYPE:
        wvsprintf(StrClass, 'M%d_Mz', @J);

      KDEAD_TYPE:
        wvsprintf(StrClass, 'D%d_Mz', @J);

      NUMLOCK_TYPE:
        wvsprintf(StrClass, 'NL%d_Mz', @J);

      SCROLLOCK_TYPE:
        wvsprintf(StrClass, 'SL%d_Mz', @J);

      CAPSLOCK_TYPE:
        wvsprintf(StrClass, 'CL%d_Mz', @J);

      else Exit;
    end;
                                                            
    KeyWndList[J] := CreateWindow(StrClass, KbKeyList[J].TextC, WS_VISIBLE or WS_CHILD or WS_BORDER, 0, 0, 0, 0, hMainWnd, J, HInstance, nil);
    if (KeyWndList[J] = 0) then Exit;
  end;

  Result := True;
end;

//
// 调整按键大小
//
function ReSizeKeys(ColMargin, RowMargin: Single): Bool;
const
  KB_DELTAKEYSIZE = 2; // increment in key size
var
  J, Width, Height: Integer; // Width and height of each window key
begin
  // for each key
  for J := Low(KbKeyList) to High(KbKeyList) do
  begin
    // Width & Height
    Width := Trunc(KbKeyList[J].kSizeX * ColMargin) + KB_DELTAKEYSIZE;
    Height := Trunc(KbKeyList[J].kSizeY * RowMargin) + KB_DELTAKEYSIZE;

    // move Keys
    MoveWindow(KeyWndList[J],
      Trunc(KbKeyList[J].PosX * ColMargin),
      Trunc(KbKeyList[J].PosY * RowMargin),
      Width, Height, True);

    // set the region we want for each key
    SetKeyRegion(KeyWndList[J], Width, Height);
  end;

  Result := True;
end;

//
// 返回按键编号
//
function LocateKey(hKeyWnd: HWnd): Integer;
begin
  for Result := Low(KeyWndList) to High(KeyWndList) do if (KeyWndList[Result] = hKeyWnd) then Exit;
  Result := -1;
end;

//
// 读取按键状态
//
function GetKeyLong(nIndex: Integer): Integer;
begin
  Result := 3;

  if (nIndex < Low(KbKeyList)) or (nIndex > High(KbKeyList)) then Exit;
  if (IsWindow(KeyWndList[nIndex]) = False) then Exit;

  Result := GetWindowLong(KeyWndList[nIndex], 0);
end;

//
// 设置按键状态
//
function SetKeyLong(nIndex, nState: Integer): Bool;
var
  hBackground: HBrush;
begin
  Result := False;

  // 超出范围
  if (nIndex < Low(KbKeyList)) or (nIndex > High(KbKeyList)) then Exit;

  // 背景画刷
  if (nState <> 0) then
    hBackground := COLOR_WINDOWTEXT + 1 // Hilite
  else
    case (KbKeyList[nIndex].kType) of
      KNORMAL_TYPE:
        hBackground := COLOR_WINDOW + 1;

      KMODIFIER_TYPE, KDEAD_TYPE, NUMLOCK_TYPE, SCROLLOCK_TYPE, CAPSLOCK_TYPE:
        hBackground := COLOR_MENU + 1;

      else Exit;
    end;
  SetClassLong(KeyWndList[nIndex], GCL_HBRBACKGROUND, hBackground);

  // 保存状态
  SetWindowLong(KeyWndList[nIndex], 0, nState);

  // 重绘按键
  InvalidateRect(KeyWndList[nIndex], nil, True);

  Result := True;
end;

//
// Round the coner of each key
//
function SetKeyRegion(hKeyWnd: HWnd; Width, Height: Integer): Bool;
var
  hKeyRgn: HRgn;
begin
  Result := False;

  hKeyRgn := CreateRoundRectRgn(1, 1, Width, Height, 5, 2);
  if (hKeyRgn = 0) then Exit;

  if (SetWindowRgn(hKeyWnd, hKeyRgn, True) = 0) then Exit;

  Result := False;
end;

//
// Redraw the keys
//
function RedrawKeys(): Bool;
var
  J: Integer;
begin
  for J := Low(KbKeyList) to High(KbKeyList) do InvalidateRect(KeyWndList[J], nil, True);
  Result := True;
end;

//
// Redraw the num lock key.
//
function RedrawNumLock(): Bool;
var
  J: Integer;
begin
  Result := True;

  for J := Low(KbKeyList) to High(KbKeyList) do
    if (KbKeyList[J].kType = NUMLOCK_TYPE) then
    begin
      if (GetKeyState(VK_NUMLOCK) and $0001 = 0) then SetKeyLong(J, 0) else SetKeyLong(J, 2);
      Exit;
    end;

  Result := False;
end;

//
// Redraw the scroll lock key.
//
function RedrawScrollLock(): Bool;
var
  J: Integer;
begin
  Result := True;

  for J := Low(KbKeyList) to High(KbKeyList) do
    if (KbKeyList[J].kType = SCROLLOCK_TYPE) then
    begin
      if (GetKeyState(VK_SCROLL) and $0001 = 0) then SetKeyLong(J, 0) else SetKeyLong(J, 2);
      Exit;
    end;

  Result := False;
end;

//
// Redraw the num caps key.
//
function RedrawCapsLock(): Bool;
var
  J: Integer;
begin
  Result := True;

  for J := Low(KbKeyList) to High(KbKeyList) do
    if (KbKeyList[J].kType = CAPSLOCK_TYPE) then
    begin
      if (GetKeyState(VK_CAPITAL) and $0001 = 0) then SetKeyLong(J, 0) else SetKeyLong(J, 2);
      Exit;
    end;

  Result := False;
end;

//
// 按键窗口回调
//
function KeyWndProc(hKeyWnd: HWnd; uMsg: UInt; wParam: WParam; lParam: LParam): LResult; stdcall;
var
  hKeyDc: HDC;
  PaintStruct: TPaintStruct;
  KeyRect: TRect;
  nIndex, nState: Integer;
begin
  case (uMsg) of
    WM_PAINT:
    begin
      nIndex := GetWindowLong(hKeyWnd, GWL_ID);
      nState := GetWindowLong(hKeyWnd, 0);
      GetClientRect(hKeyWnd, KeyRect);

      hKeyDc := BeginPaint(hKeyWnd, PaintStruct);

      case (nState) of
        0: // 普通状态
        begin
          case (KbKeyList[nIndex].Name) of
            BITMAP:
              DrawKeyBmp(hKeyDc, KbKeyList[nIndex].TextL, KeyRect);

            ICON:
              DrawKeyIcon(hKeyDc, KbKeyList[nIndex].TextL, KeyRect);

            else
              DrawKeyText(hKeyDc, KeyRect, nIndex, nState);
          end;
        end;

        1: // 路过状态
        begin
          case (KbkeyList[nIndex].Name) of
            BITMAP:
              DrawKeyBmp(hKeyDc, KbKeyList[nIndex].SkLow, KeyRect);

            ICON:
              DrawKeyIcon(hKeyDc, KbKeyList[nIndex].SkLow, KeyRect);

            else
              DrawKeyText(hKeyDc, KeyRect, nIndex, nState);
          end;

          DrawKeyRed(hKeyDc, KeyRect);
        end;

        2: // 按下状态
        begin
          case (KbkeyList[nIndex].Name) of
            BITMAP:
              DrawKeyBmp(hKeyDc, KbKeyList[nIndex].SkLow, KeyRect);

            ICON:
              DrawKeyIcon(hKeyDc, KbKeyList[nIndex].SkLow, KeyRect);

            KB_CAPLOCK,
            KB_NUMLOCK,
            KB_SCROLL:
            begin
              DrawKeyText(hKeyDc, KeyRect, nIndex, nState);
              DrawKeyLight(hKeyDc, KeyRect);
            end;

            else
              DrawKeyText(hKeyDc, KeyRect, nIndex, nState);
          end;

          DrawKeyRed(hKeyDc, KeyRect);
        end;
      end; // case (nState) of ..

      EndPaint(hKeyWnd, PaintStruct);
      Result := 0;
    end;

    WM_MOUSEACTIVATE:
    begin
      Result := MA_NOACTIVATEANDEAT; // 不激活窗体, 并删除鼠标消息..
    end;

    else
      Result := DefWindowProc(hKeyWnd, uMsg, wParam, lParam);
  end; // case (uMsg) of ..
end;

//
// 红色边框
//
function DrawKeyRed(hKeyDc: HDC; Rect: TRect): Bool;
const
  lpRed: TLogPen = (lopnStyle: PS_SOLID; lopnWidth: (x: 2; y: 2); lopnColor: $0000FF);
var
  Points: array[0..2] of TPoint;
  hOldPen, hNewPen: HPen;
begin
  Result := False;

  hNewPen := CreatePenIndirect(lpRed);
  if (hNewPen = 0) then Exit else hOldPen := SelectObject(hKeyDc, hNewPen);

  Points[0].x := Rect.Right - 1;
  Points[0].y := 2;
  Points[1].x := Rect.Right - 1;
  Points[1].y := Rect.Bottom - 1;
  Points[2].x := 0;
  Points[2].y := Rect.Bottom - 1;
  Result := Polyline(hKeyDc, Points, 3);

  Points[0].x := 1;
  Points[0].y := Rect.Bottom;
  Points[1].x := 0;
  Points[1].y := 0;
  Points[2].x := Rect.Right;
  Points[2].y := 1;
  Result := Polyline(hKeyDc, Points, 3) and Result;

  SelectObject(hKeyDc, hOldPen);
  DeleteObject(hNewPen);
end;

//
// 绘制图标
//
function DrawKeyIcon(hKeyDc: HDC; pIconName: PChar; Rect: TRect): Bool;
var
  hKeyIcon: HIcon;
  xLeft, yTop: Integer;
begin
  Result := False;

  hKeyIcon := LoadImage(HInstance, pIconName, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE or LR_SHARED);
  if (hKeyIcon = 0) then
  begin
    SendErrorMessage(IDS_CANNOT_LOAD_ICON);
    Exit;
  end;

  // Find out where is the top left corner to place the icon
  xLeft := (Rect.Right - Rect.Left) div 2 - 16;
  yTop := (Rect.Bottom - Rect.Top) div 2 - 16;

  // Draw the icon (Draw in center)
  SetMapMode(hKeyDc, MM_TEXT);
  Result := DrawIconEx(hKeyDc, xLeft, yTop, hKeyIcon, 0, 0, 0, 0, DI_NORMAL);
end;

//
// 绘制位图
//
function DrawKeyBmp(hKeyDc: HDC; pBmpName: PChar; Rect: TRect): Bool;
var
  hKeyBmp: HBitMap;
  hMemDc: HDC;
  Width, Height: Integer;
begin
  Result := False;

  hKeyBmp := LoadImage(HInstance, pBmpName, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE or LR_SHARED);
  if (hKeyBmp = 0) then
  begin
    SendErrorMessage(IDS_CANNOT_LOAD_ICON); // **
    Exit;
  end;

  Width := Rect.Right - Rect.Left - 2;
  Height := Rect.Bottom - Rect.Top - 2;

  SetMapMode(hKeyDc, MM_TEXT);
  hMemDc := CreateCompatibleDC(hKeyDc);
  SelectObject(hMemDc, hKeyBmp);

  // Leave 1 pixels for drawing border
  Result := StretchBlt(hKeyDc, 1, 1, Width, Height, hMemDc, 0, 0, Width, Height, SRCCOPY);
  DeleteDC(hMemDc);
end;

//
// print out str in the center of Rect (绘制文字)
//
function DrawKeyText(hKeyDc: HDC; Rect: TRect; nIndex, nState: Integer): Bool;
var
  KeyState: TKeyboardState;
  VirtualKey: UInt;
  cBuffer: array[0..30] of Char;
  OutText: PChar;
  OutSize: TSize;
  OutLength, OutPosX, OutPosY: Integer;
  OldBkMode: Integer;
  hNewFont, hOldFont: HFont;
begin
  Result := False;

  // 文本
  case (KbKeyList[nIndex].Print) of
    1: begin
      GetKeyboardState(KeyState);
      KeyState[VK_CONTROL]  := 0; // **
      KeyState[VK_LCONTROL] := 0;
      KeyState[VK_RCONTROL] := 0;
      VirtualKey := MapVirtualKey(KbKeyList[nIndex].ScanCode[0], 1);
      cBuffer[0] := #0;
      ToAscii(VirtualKey, KbKeyList[nIndex].ScanCode[0], KeyState, cBuffer, 0);
      cBuffer[1] := #0;      
      OutText := @cBuffer;
    end;

    2: begin
      if (GetKeyState(VK_SHIFT) and $1000 = 0) then
        OutText := KbKeyList[nIndex].TextL  // Print lower
      else
        OutText := KbKeyList[nIndex].TextC; // Print Cap
    end;

    3: begin
      if (GetKeyState(VK_NUMLOCK) and $0001 = 0) then
        OutText := KbKeyList[nIndex].SkLow
      else
        OutText := KbKeyList[nIndex].SkCap;
    end;

    else Exit;
  end;

  // 字体
  hNewFont := CreateFontIndirect(KbInfo.DefaultFont);
  if (hNewFont <> 0) then hOldFont := SelectObject(hKeyDc, hNewFont) else hOldFont := 0;

  // 背景
  OldBkMode := SetBkMode(hKeyDc, TRANSPARENT);

  // 颜色
  if (nState <> 0) then
    SetTextColor(hKeyDc, GetSysColor(COLOR_HIGHLIGHTTEXT)) // Hilite
  else
    if (KbKeyList[nIndex].kType = KMODIFIER_TYPE) or
       (KbKeyList[nIndex].kType = NUMLOCK_TYPE) or
       (KbKeyList[nIndex].kType = SCROLLOCK_TYPE) or
       (KbKeyList[nIndex].kType = CAPSLOCK_TYPE)
    then
      SetTextColor(hKeyDc, GetSysColor(COLOR_INACTIVECAPTION)) // Modifier
    else
      SetTextColor(hKeyDc, GetSysColor(COLOR_BTNTEXT)); // Normal

  // 位置
  OutLength := lStrLen(OutText);
  GetTextExtentPoint32(hKeyDc, OutText, OutLength, OutSize);
  OutPosX := ((Rect.Right - Rect.Left) - OutSize.cx) div 2;
  OutPosY := ((Rect.Bottom - Rect.Top) - OutSize.cy) div 2;

  // 绘制
  Result := TextOut(hKeyDc, OutPosX, OutPosY, OutText, OutLength);

  // 清除
  SetBkMode(hKeyDc, OldBkMode);
  SelectObject(hKeyDc, hOldFont);
  DeleteObject(hNewFont);
end;

//
// Draw the keys LED light ( Lock灯 )
//
function DrawKeyLight(hKeyDc: HDC; Rect: TRect): Bool;
const
  sIconName = 'LED_LIGHT';
var
  hKeyIcon: HIcon;
begin
  Result := False;

  hKeyIcon := LoadImage(HInstance, sIconName, IMAGE_ICON, Rect.Right, Rect.Bottom, LR_SHARED);
  if (hKeyIcon = 0) then
  begin
    SendErrorMessage(IDS_CANNOT_LOAD_ICON);
    Exit;
  end;

  SetMapMode(hKeyDc, MM_TEXT);
  Result := DrawIconEx(hKeyDc, 2, 2, hKeyIcon, Rect.Right, Rect.Bottom, 0, 0, DI_NORMAL);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -