- GetAsyncKeyState
-
function GetAsyncKeyState(vKey: Integer): SHORT; stdcall;
キーが押されているかどうかを判定するには、
function gfnbKeyState(iKey: Integer): Boolean;
begin
//マウスの左右ボタンを入れ替えている場合に対処
if (GetSystemMetrics(SM_SWAPBUTTON) <> 0) then begin
if (iKey = VK_LBUTTON) then begin
iKey := VK_RBUTTON;
end else if (iKey = VK_RBUTTON) then begin
iKey := VK_LBUTTON;
end;
end;
Result := BOOL(Hi(GetAsyncKeyState(iKey)));
end;
とします。
入力フォーカスがないときでもタイマーを使ってこの関数を呼べばフックを使わなくてもキー入力を監視できます。
お手軽です。
上の例では最下位ビットの値は調べていませんが、きちんと最下位ビットの状態も調べて判定に加えるとよりよい判定ができるのではないかと思いました。
ということで実際にやってみた結果、マウスとキーボードで挙動が違うことが分かりました。
どちらもずっと押しっぱなしでやってみたところ Lo(li_Key) の値は、
マウスボタンの場合、押し始めの一回だけ1であとはずっと0が返ります。
キーボードのキーの場合、押し始めの一回が1であとはちょっとの間0が続き、その後ずっと1が返ります。
キーボードからの入力でキーを押しっぱなしにすると一回入力の後タイムラグがあり、その後ダダダダダと入力が続きます。
多分そのタイムラグ(ディレイタイム)なのであろうと思われます。
ということでキー入力のシミュレートをするにはこの最下位ビットを判定に加えるのが良いのでしょう。
function gfnbKeyState(iKey: Integer): Boolean;
var
li_Code: SHORT;
begin
//マウスの左右ボタンを入れ替えている場合に対処
if (GetSystemMetrics(SM_SWAPBUTTON) <> 0) then begin
if (iKey = VK_LBUTTON) then begin
iKey := VK_RBUTTON;
end else if (iKey = VK_RBUTTON) then begin
iKey := VK_LBUTTON;
end;
end;
li_Code := GetAsyncKeyState(iKey);
Result := BOOL(Hi(li_Code)) and BOOL(Lo(li_Code));
end;
キー入力のシミュレートが目的ではなく、単にキーやマウスボタンが押されているかを調べたい場合は最上位ビットだけの判定の方が良いようです。
最下位ビットの判定も加えると、キーボードの場合ディレイタイムの間は取りこぼしがありますしマウスボタンの場合最初の一回だけしか押されていると判定されないので使いづらいと思われるので。
- GetPixel
-
function GetPixel(DC: HDC; X, Y: Integer): COLORREF; stdcall;
X, Yはクライアント座標。
var
lpt_Pos: TPoint;
lh_WND: HWND;
lh_DC: HDC;
li_Color: COLORREF;
begin
GetCursorPos(lpt_Pos);
lh_WND := WindowFromPoint(lpt_Pos);
lh_DC := GetDC(lh_WND);
Windows.ScreenToClient(lh_WND, lpt_Pos);
li_Color := GetPixel(lh_DC, lpt_Pos.X, lpt_Pos.Y);
if (lh_Color <> CLR_INVALID) then begin
Beep;
Label1.Color := li_Color;
end;
ReleaseDC(lh_WND, lh_DC);
クライアント領域外の色は取得できません。
例えば上の例では、タイトルバーやメニューバー、フォームのフレームなどはクライアント領域外なのでNG 。
- lstrcpyn lstrcpynW
-
function lstrcpyn(lpString1, lpString2: PChar; iMaxLength: Integer): PChar; stdcall;
function lstrcpynW(lpString1, lpString2: PWideChar; iMaxLength: Integer): PWideChar;
stdcall;
iMaxLengthはプラットフォーム SDKによると
iMaxLength
lpString2 パラメータが指す文字列から、lpString1 パラメータが指すバッファへコピーするべき文字の数を
TCHAR 単位で指定します。終端の NULL 文字分も含めてください。
となっています。
終端のNULL文字も含めてとなっているので、
lstrcpyn(lp_Buff, PAnsiChar(ls_Str), Length(ls_Str) +1);
のようにコピーする文字数 +1(終端のNULL分)としなければなりません。
単純に、
lstrcpyn(lp_Buff, PAnsiChar(ls_Str), Length(ls_Str));
のようにしてしまうと最後の一文字が欠けます。
- SystemParamtersInfo
-
function SystemParametersInfo(uiAction, uiParam: UINT; pvParam: Pointer; fWinIni:
UINT): BOOL; stdcall;
引数fWinIniは,システムパラメータの設定をユーザープロファイルとして更新するかどうか,また更新する場合はすべてのトップレベルウィンドウへ送信して,変更が生じたことを通知するかどうかを指定します.どちらも行わない場合は0を指定します.
SystemParamtersInfo関数のfWinIni引数の値
SPIF_UPDATEINIFILE |
システム全体のパラメータに関する新しい設定を,ユーザープロファイルに書き込む. |
SPIF_SENDCHANGE |
ユーザープロファイルを更新した後,WM_SETTIMGCHANGEメッセージをブロードキャストする. |
SPIF_SENDWININICHANGE |
SPIF_SENDCHANGと同じ. |
ユーザープロファイルを更新して変更を通知するにはSPIF_SENDCHANGEだけでいけそうに思えたのですが、SPIF_UPDATEINIFILE
or SPIF_SENDCHANGEとしなければなりません。
SPIF_SENDCHANGEだけではSPIF_UPDATEINIFILEだけを指定した場合と同じ結果になるようです。
- TextOutW ExtTextOutW DrawTextW
-
procedure TForm1.Button1Click(Sender: TObject);
var
lrc_Rect: TRect;
ls_Text: WideString;
begin
ls_Text := '';
ls_Text := ls_Text + WideChar($BBF8) + WideChar($C548); //미안
Image1.Canvas.Font.Assign(Edit1.Font);
Image2.Canvas.Font.Assign(Edit1.Font);
Image3.Canvas.Font.Assign(Edit1.Font);
Image1.Canvas.FillRect(Image1.ClientRect);
TextOutW(Image1.Canvas.Handle, 0, 0, PWideChar(ls_Text), Length(ls_Text));
Image2.Canvas.FillRect(Image2.ClientRect);
lrc_Rect := Image2.ClientRect;
DrawTextW(Image2.Canvas.Handle, PWideChar(ls_Text), -1, lrc_Rect,
DT_NOPREFIX);
Image3.Canvas.FillRect(Image3.ClientRect);
ExtTextOutW(Image3.Canvas.Handle, 0, 0, 0, @lrc_Rect, PWideChar(ls_Text),
Length(ls_Text), nil);
end;
ハングルだけの文字列を出力した場合TextOutWとExtTextOutWは文字化けします。
DrawTextWはちゃんと表示します。
ただしFontのNameが'MS UI Gothic'の場合はどれもちゃんと表示されます。
反対に'MS Pゴシック'の場合はどれも文字化けします。
さらにフォントのCharsetプロパティに以下の四つを指定するとどれもちゃんと表示されます。
CHINESEBIG5_CHARSET
GB2312_CHARSET
HANGEUL_CHARSET
THAI_CHARSET
またハングルにひらがなや漢字などが混じるとどれもちゃんと表示されます。
半角アルファベットや半角数字・記号などが混じっただけでは文字化けは直りません。
#13などの制御文字が混じるとちゃんと表示されます。
ややこしいです。
なので文字列の出力にはDrawTextW推奨。