PDA

Просмотр полной версии : C#+WinAPI отправка сообщений в окно


FlyBird
15.04.2010, 10:33
У меня возникла проблема.
Не получается отправить в окно сообщение о нажатой кнопке F1
Капаюсь уже в таблицах ассема, в лекциях с инста, но разве в них что-то найдешь после 2-х лет перекладывания с места на место.
/

//**********WinAPI функции*********

[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string _ClassName, string _WindowName);

[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndPrnt, IntPtr hwndChildAfter, string _ClassName, string _WindowName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int DestroyWindow(IntPtr hWnd);

//*********/WinAPI функции*********



**********WinAPI константы*********
const int BM_SETSTATE = 243;
const int WM_LBUTTONDOWN = 513;
const int WM_LBUTTONUP = 514;
const int WM_KEYDOWN = 256;
const int WM_CHAR = 258;
const int WM_KEYUP = 257;
const int WM_SETFOCUS = 7;
const int WM_SYSCOMMAND = 274;
const int SC_MINIMIZE = 32;
const int WM_CLOSE = 0x0010;
//*********/WinAPI константы*********

...
...
...
private void SentMes_Click(object sender, EventArgs e)
{

IntPtr hWnd = FindWindow(null, comboBox1.SelectedItem.ToString());
IntPtr t1;
if (hWnd == IntPtr.Zero)
{
MessageBox(new IntPtr(0), "Not found main", "Error", 0);
return;
}


retValue = SendMessage(hWnd, WM_SETFOCUS, nul, nul);
retValue = SendMessage(hWnd, WM_KEYDOWN, t1, nul);
retValue = SendMessage(hWnd, WM_KEYUP, t1, nul);
}

Где-то тут зарылся косяк.
В тестируется все в блокноте. Сообщения о нажатых символах идут. Но если отправить код 112, то напишется буква. Помню, что у системных клавишь 2 кода, но вот хоть убейте, не могу вспомнить второй и как его отправить.

Может кто чем поможет?

Feonor
15.04.2010, 22:34
какая буква пишется?)

flacs
15.04.2010, 23:57
На Delphi

procedure SendShift(H: HWnd; Down: Boolean);
var vKey, ScanCode, wParam: Word;
lParam: longint;
begin
vKey:= $10;
ScanCode:= MapVirtualKey(vKey, 0);
wParam:= vKey or ScanCode shl 8;
lParam:= longint(ScanCode) shl 16 or 1;
if not(Down) then lParam:= lParam or $C0000000;
SendMessage(H, WM_KEYDOWN, vKey, lParam);
end;

procedure SendCtrl(H: HWnd; Down: Boolean);
var vKey, ScanCode, wParam: Word;
lParam: longint;
begin
vKey:= $11;
ScanCode:= MapVirtualKey(vKey, 0);
wParam:= vKey or ScanCode shl 8;
lParam:= longint(ScanCode) shl 16 or 1;
if not(Down) then lParam:= lParam or $C0000000;
SendMessage(H, WM_KEYDOWN, vKey, lParam);
end;


procedure SendKey(H: Hwnd; Key: char);
var vKey, ScanCode, wParam: Word;
lParam, ConvKey: longint;
Shift, Ctrl: boolean;
begin
ConvKey:= OemKeyScan(ord(Key));
Shift:= (ConvKey and $00020000) <> 0;
Ctrl:= (ConvKey and $00040000) <> 0;
ScanCode:= ConvKey and $000000FF or $FF00;
vKey:= ord(Key);
wParam:= vKey;
lParam:= longint(ScanCode) shl 16 or 1;
if Shift then SendShift(H, true);
if Ctrl then SendCtrl(H, true);
SendMessage(H, WM_KEYDOWN, vKey, lParam);
SendMessage(H, WM_CHAR, vKey, lParam);
lParam:= lParam or $C0000000;
sleep(50);
SendMessage(H, WM_KEYUP, vKey, lParam);
if Shift then SendShift(H, false);
if Ctrl then SendCtrl(H, false);
end;


SendKey(FindWindow(),'F');

BrainDeaD
16.04.2010, 00:19
Key.F1 слать пробовал?

FlyBird
16.04.2010, 10:01
Мне же не только F1 отправить нужно. Но и F2, F3, F4 и т.д.
Вообще системные клавиши.

flacs
16.04.2010, 10:29
коды виртуальных клавиш
F1 - F12 (112 - 123), соотвественно

Пример отправки F1


SendKey(FindWindow(),chr(112));

FlyBird
16.04.2010, 14:17
коды виртуальных клавиш
F1 - F12 (112 - 123), соотвественно

Пример отправки F1


Вероятно вы просто не заметили. Одно из этих числ было указано в первом топике (112). Если послать сообщение с кодом 112 то окно поймет, что вы ему шлете код символа, который похож на "р", а не как не F1.
Попробуйте в блокном отправить код 116 (вроде как F5 должно быть). Если в блокноте появится дата и время, то это действительно F5. Но скорее всего будет символ.

У системных клавишь 2 кода. Один совпадает с символом, другой говорит ОС, что была нажата системная клавишь.

St0nX
16.04.2010, 14:51
Вообщем проблема может быть еще в том что ты не в то окно шлеш. Попробуй дочернии поперебирать.

FlyBird
16.04.2010, 15:07
Окно то. Сообщение о закрытии окна получает то окно, которое я хочу закрыть.
Что качается блокнота. Если я хочу написать символ, то он его пишет. Коды верно воспринимает, а вот системные кнопки нет

St0nX
16.04.2010, 15:55
http://www.edgeofnowhere.cc/viewtopic.php?t=396398

FlyBird
19.04.2010, 13:05
Похоже на то, что мне нужно. Спасибо, буду дальше махиначить

FlyBird
22.04.2010, 11:00
И все же это чуточку не то.
У него такого же рода проблема. Список констант, которые вроде пашут, а вроде и нет.

ViLKaa
22.04.2010, 12:07
Эм...
SendKeys.Send("{F1}");

или я что то не понимаю)

FlyBird
23.04.2010, 18:57
Что-то тогда не ясно, как отправить это окну, которое в фокусе.

FlyBird
23.04.2010, 20:27
Решение найдено.
Вилка прав(а)
http://msdn.microsoft.com/en-us/library/ms171548.aspx

FlyBird
17.05.2010, 10:21
Что-то замучала эта задачка.
Когда идет посылка SendKeys.Send("{F1}"); приходится ждать ответа.
А я хочу слать кажду секунду сообщение о нажатой кнопке .

W!z@rD
17.05.2010, 10:51
DDoS какой-то.

надо учитывать что SendKeys отправляет сообщение активному окну.

чтобы не ждать "ответа" нужно асинхронно посылать сообщения.

FlyBird
17.05.2010, 10:52
Неее... можно выставить, что типо окно в фокусе и слать ему сообщения, хотя ты его сам активным не делаешь.

alexey-m
17.05.2010, 15:48
Что-то замучала эта задачка.
Когда идет посылка SendKeys.Send("{F1}"); приходится ждать ответа.
А я хочу слать кажду секунду сообщение о нажатой кнопке .
FlyBird, если не охота ждать то посылай сообщения через PostMessage, так сообщения ставятся в очередь и ты сразу получишь управления после вызова функции, при использовании SendMessage сообщения отправляются на прямую, и тебе придется ждать...
Раз ты проверял все на блокноте то небольшой пример, правда на Delphi

procedure TFormMain.Button1Click(Sender: TObject);
var
hWnd,hChild: THandle;
begin
// Ещем окно с классом 'Notepad'
hWnd:= FindWindowA('Notepad',nil);
if hWnd<>0 then begin
hChild:= FindWindowExA(hWnd,0,'Edit',nil); // Ищем текстовое поле
if hChild<>0 then begin
SendMessage(hChild, WM_CHAR, Word('-'), 0); // Посылаем символ "-"
PostMessage(hChild, WM_KEYDOWN, VK_RETURN, 0); // Переводим строку
end;
PostMessage(hWnd, WM_KEYDOWN, VK_F5, 0); // Посылаем главному окну о нажатии клавиши F5
end else
ShowMessage('Notepad not found');
end;

FlyBird
20.05.2010, 11:17
FlyBird, если не охота ждать то посылай сообщения через PostMessage, так сообщения ставятся в очередь и ты сразу получишь управления после вызова функции, при использовании SendMessage сообщения отправляются на прямую, и тебе придется ждать...
Раз ты проверял все на блокноте то небольшой пример, правда на Delphi

procedure TFormMain.Button1Click(Sender: TObject);
var
hWnd,hChild: THandle;
begin
// Ещем окно с классом 'Notepad'
hWnd:= FindWindowA('Notepad',nil);
if hWnd<>0 then begin
hChild:= FindWindowExA(hWnd,0,'Edit',nil); // Ищем текстовое поле
if hChild<>0 then begin
SendMessage(hChild, WM_CHAR, Word('-'), 0); // Посылаем символ "-"
PostMessage(hChild, WM_KEYDOWN, VK_RETURN, 0); // Переводим строку
end;
PostMessage(hWnd, WM_KEYDOWN, VK_F5, 0); // Посылаем главному окну о нажатии клавиши F5
end else
ShowMessage('Notepad not found');
end;


Спасибо большое за ответ.
За пару дней до вашего я все же достиг того, что нужно. Помогли на одном форуме. Я что-то совсем про ПОСТ забыл.
Даже был вариант самому себе посылать подтверждение, но потом напомнили про ПОСТ. WipAPI только в инсте проходил и ни шагу дальше.
Пример кода.



if (hWnd == IntPtr.Zero)
{
MessageBox.Show("Процесс не найден", "FlyBird(Ошибка)");
return;
}
IntPtr hEdit = FindWindowEx(hWnd, IntPtr.Zero, "Edit", "");
if (hEdit == IntPtr.Zero)
{
MessageBox.Show("Not found child", "Error");
return;
}

IntPtr t1 = (IntPtr)ComBoxSelectItem_1;
IntPtr nul = IntPtr.Zero;

//PostMessage(hWnd, WM_KEYUP, t1, nul);
PostMessage(hWnd, WM_KEYDOWN, t1, nul);



Теперь проблема в том, как достучаться до меню сторонний программы и отправить команду на выполнения поункта меню и дальше вбить в TextBox нужные символы и нажать Button.