お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"スケルトンソフトキーボード"





Memo上で透過して使えるソフトキーボード(とりあえずテンキーのみ)です。
見た目はチャッチーですが、編集時に邪魔にならないのがウリです。
サブクラス化はデルマガ4月号 「TMemoの背景にビットマップを貼る」を
参考にさせてもらいました、ありがとうございました。

皆さんの添削をお待ちしております(^^)

☆準備
 Form1の上に、Memo1、Label1、Button1を置きます。

☆補足
 Delphi4 でテスト。


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Label1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Label1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    FMemo1OldWndProc: TWndMethod;
    procedure Memo1NewWndProc(var Message: TMessage);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const
  iCOL = 9;
  iROW = 9;
var
  FDragXPos: Integer;
  FDragYPos: Integer;
  FDragging: Boolean;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //Memo1をサブクラス化
  FMemo1OldWndProc := Memo1.WindowProc;
  Memo1.WindowProc := Memo1NewWndProc;
  //Memo1上にラベルのソフトキーセット
  Label1.Parent := Memo1;
  Label1.Font.Color := clPurple;
  Label1.Font.Name := 'MS ゴシック'; //プロポーショナルフォントは不可
  Label1.Font.Size := 12; //9, 12, 15など3の倍数にする
  Label1.Caption := '┏━━━━━━━┓'#13#10
                  + '┃      X┃'#13#10
                  + '┠─┬─┬─┬─┨'#13#10
                  + '┃0│1│2│3┃'#13#10
                  + '┠─┼─┼─┼─┨'#13#10
                  + '┃4│5│6│7┃'#13#10
                  + '┠─┼─┼─┼─┨'#13#10
                  + '┃8│9│BS│CR┃'#13#10
                  + '┗━┷━┷━┷━┛';
  Label1.Cursor := crArrow;
  Label1.Transparent := True;
  Label1.Left := Memo1.Width div 2 - Label1.Width div 2;
  Label1.Top := Memo1.Height div 2 - Label1.Height div 2;
  FDragging := False;
end;

procedure TForm1.Memo1NewWndProc(var Message: TMessage);
begin
  //元のウィンドウプロシージャを呼び出す
  FMemo1OldWndProc(Message);
  if Message.Msg = CN_COMMAND then begin
    //文字列が変更されたら Label1を再描画させる
    if Message.WParamHi = EN_UPDATE then begin
      Label1.Invalidate;
    end
    //内部でスクロールが発生したら Memo1全体を再描画させる
    else if (Message.WParamHi = EN_HSCROLL) or
            (Message.WParamHi = EN_VSCROLL) then begin
      Memo1.Invalidate;
    end;
  end
  //スクロールバーが操作されたら Memo1全体を再描画
  else if (Message.Msg = WM_HSCROLL) or
          (Message.Msg = WM_VSCROLL) then begin
    Memo1.Invalidate;
  end;
end;

procedure TForm1.Label1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  iC, iR, iX, iY, iW, iH, iNum: Integer;
  iTCol: Integer;
begin
  with Sender as TLabel do begin
    iTCol := (iCOL - 1) div 2;//実際の列数
    iC := Width * 2 div iCOL; //列幅
    iR := Height * 2 div iROW;//行高さ
    iX := X - iC div 4;       //実際のキーボード上のX位置
    iY := Y - iR div 4;       //実際のキーボード上のY位置
    iW := Width - iC div 2;     //実際のキーボード幅
    iH := Height - iR div 2;    //実際のキーボード高さ
    if (iX < 0) or (iW < iX) or (iY < 0) or (iH < iY) then Exit;
    if iR < iY then begin               //2行目以降?
      iNum := iX div iC + (iY div iR - 1) * iTCol;
      case iNum of
       0..9: begin
        SendMessage(Memo1.handle, WM_CHAR, Ord('0') + iNum, 0);
       end;
       10: begin
        SendMessage(Memo1.handle, WM_CHAR, VK_BACK, 0);
       end;
       11: begin
        SendMessage(Memo1.handle, WM_CHAR, VK_RETURN, 0);
       end;
      end;
    end
    else begin
      if iW * (iTCol - 1) div iTCol < iX then begin //4列目?
        TLabel(Sender).Visible := False;
      end
      else begin
        FDragXPos := X;
        FDragYPos := Y;
        FDragging := True;
      end;
    end;
  end;
end;

procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  with Sender as TLabel do begin
    if FDragging then begin
      Left := Left + X - FDragXPos;
      Top := Top + Y - FDragYPos;
    end;
    if Left < 0 then Left := 0;
    if Memo1.Width < Left + Width then Left := Memo1.Width - Width;
    if Top < 0 then Top := 0;
    if Memo1.Height < Top + Height then Top := Memo1.Height - Height;
  end;
end;

procedure TForm1.Label1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FDragging := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Visible := True;
end;

end.
                                     99/09/20(月) 07:43 sai(FZA01256)

Original document by sai             氏 ID:(FZA01256)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum