Перейти к содержимому

Фотография

Помогите сделать экранную клавиатуру на Delphi


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 8

#1
CrazyDogNekkid

CrazyDogNekkid
  • Гость
  • 19 сообщений
Народ, помогите пожалуйста.
Пытался сделать на Delphi экранную клавиатуру на подобии Виндовозной, проблема не с оформлением, а как сымитировать нажатие той или иной клавиши. Максимум что у меня получилось это открыть "пуск":

procedure TForm1.Button1Click(Sender: TObject);
begin
sendmessage(handle,wm_syscommand,sc_tasklist,0);
end;
  • 0

#2
kukushka

kukushka
  • Постоялец
  • 449 сообщений
Если я не ошибаюсь есть команда wm_keyPress или чтото похожее, и параметр какая клавиша.
  • 0

#3
dantl

dantl
  • Завсегдатай
  • 188 сообщений
При нажатии на клавиатуру Windows генерирует несколько событий.
WM_KEYDOWN, WM_CHAR и WM_KEYUP.
Если вы удерживаете клавишу Alt во время нажатия пробел, минус и пробел F10, то эти события трансформируются в системные события и нажатия клавиш приложение в обычном обработчике WndProc не видит.

Т.о. чтобы сыимитировать нажатие нужно послать три сообщения окну приложения.
SendMessage( handle, WM_KEYDOWN, VK_XXX, ....
WPARAM это виртуальный код клавиши ...
относительно LPARAM нужно читать документацию в MSDN для событий KEYDOWN, KEYUP ...
  • 0

#4
CrazyDogNekkid

CrazyDogNekkid
  • Гость
  • 19 сообщений
Так народ, я попробовал сделать следующее: я создал форму и кнопку и создал события на форме и кнопке OnKeyPress, в которых ввел проверку, если KEY = #27 {Esc} then form1.close. На кнопку я прописал SendMessage(handle,wm_keydown,vk_escape,0); и SendMessage(handle,wm_keyup,vk_escape,0); и вообщем форма не закрылась, поэтому прошу написать пример.

На всякий случай.
unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure Button1KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
sendmessage(handle,wm_keyup,VK_ESCAPE,0);
sendmessage(handle,wm_keydown,VK_ESCAPE,0);
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if key=#27 then close;
end;

procedure TForm1.Button1KeyPress(Sender: TObject; var Key: Char);
begin
if key=#27 then close;
end;

end.
  • 0

#5
Ultra-AM

Ultra-AM
  • В доску свой
  • 1 517 сообщений
Полезно заглядывать не только в обычный дельфишный хелп, но и в Windows SDK :rolleyes:

The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.

VOID keybd_event(

BYTE bVk, // virtual-key code
BYTE bScan, // hardware scan code
DWORD dwFlags, // flags specifying various function options
DWORD dwExtraInfo // additional data associated with keystroke
);


Parameters

bVk

Specifies a virtual-key code. The code must be a value in the range 1 to 254.

bScan

Specifies a hardware scan code for the key.

dwFlags

A set of flag bits that specify various aspects of function operation. An application can use any combination of the following predefined constant values to set the flags:

Value Meaning
KEYEVENTF_EXTENDEDKEY If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
KEYEVENTF_KEYUP If specified, the key is being released. If not specified, the key is being depressed.


dwExtraInfo

Specifies an additional 32-bit value associated with the key stroke.



Return Values

This function has no return value.

Remarks

Although keybd_event passes an OEM-dependent hardware scan code to Windows, applications should not use the scan code. Windows converts scan codes to virtual-key codes internally and clears the up/down bit in the scan code before passing it to applications.
An application can simulate a press of the PRINTSCREEN key in order to obtain a screen snapshot and save it to the Windows clipboard. To do this, call keybd_event with the bVk parameter set to VK_SNAPSHOT, and the bScan parameter set to 0 for a snapshot of the full screen or set bScan to 1 for a snapshot of the active window.
  • 0

#6
dantl

dantl
  • Завсегдатай
  • 188 сообщений
keybd_event заменена в NT4/2000/XP на SendInput, но суть этих функций это вставка сообщений непосредственно в поток ввода клавиатуры, мыши. Необходимы эти функции например когда нужно сделать принтскрин, или если вы разрабатываете систему ввода голосом...

Для того чтобы ваше приложение могло отправлять сообщение другому окну достаточно сделать следующее
::SendMessage( (HWND)m_hWndReceiver, WM_KEYDOWN, 'A', 0 );
::SendMessage( (HWND)m_hWndReceiver, WM_CHAR, 'A', 0 );
::SendMessage( (HWND)m_hWndReceiver, WM_KEYUP, 'A', 0 );
Проверил работает.
В качестве m_hWndReceiver я использовал HWND полученный в Spy от окна приложения Notepad буква A в нем чудесно печатается...
  • 0

#7
CrazyDogNekkid

CrazyDogNekkid
  • Гость
  • 19 сообщений
Большое спасибо dantl и Ultra-AM (конечно я не очень понял что ты написал, но приятно, когда народ не молчит). Я проверил, помоему достаточно только
::SendMessage( handle, WM_CHAR, vk_escape, 0 ); // по крайне мере в моем примере работает.

Ultra-AM ,а можно еще раз, а лучше пример, а еще лучше на Delphi пример (извини, если назойлив :().
  • 0

#8
Ultra-AM

Ultra-AM
  • В доску свой
  • 1 517 сообщений
CrazyDogNekkid, это же как раз из дельфишного хелпа, только это хелп по функциям виндолс...
просто напишите keybd_event и поставьте скобку "("
выйдет хинт где написано что ей нужно, виртуальный код клавиши, скэн код, какой-то флаг и еще какое-то значение ...
последние два - просто числа. Непомню, возможно подойдут просто "0"...
попробуйте, хелп посмотрите...
правда она работает только с активным окном, т.е. то куда вам нужно послать символ - должно быть активным.
  • 0

#9
dantl

dantl
  • Завсегдатай
  • 188 сообщений
Если нужно правильно собрать LPARAM, так на всякий случай

UINT scancode = MapVirtualKey( 'A', 0 );
r = SendMessage( w, WM_KEYDOWN, 'A', ULONG(1)|(scancode<<16)|(1<<30) );
  • 0


Количество пользователей, читающих эту тему: 1

пользователей: 0, неизвестных прохожих: 1, скрытых пользователей: 0

Размещение рекламы на сайте     Предложения о сотрудничестве     Служба поддержки пользователей

© 2011-2022 vse.kz. При любом использовании материалов Форума ссылка на vse.kz обязательна.