2011-02-28 2 views
3

Я хочу сохранить окно TextPad с помощью кода C#; Я могу узнать дескриптор окна, но не знаю, как отправить CTRL-S в это окно. Я хочу использовать API P/Invoke для этого. Кроме того, это окно TextPad будет неактивным, потому что мое приложение будет активным в это время.Отправка сообщения CTRL-S в окно

[DllImport("user32.dll")] 
private static extern int SendMessage(IntPtr hwnd, int msg, int wParam, int lParam); 

Send Ctrl+Up to a window

Я смотрел на эту дискуссию, которая очень похожа на мою проблему. Я понимаю, логически следует, что я должен сделать 4 отправлять сообщения, как показано ниже

  • KeyDown клавишу CTRL
  • KeyDown клавишу S.
  • KeyUp S ключ
  • KeyUp CTRL ключ

Я не уверен, как отправить правильные параметры в SendMessage. Чтобы закрыть окно, я использую

SendMessage(hWnd, 0x0010, 0, 0); 

Я получил это из библиотеки MSDN.

Можете ли вы направить меня на какую-либо ссылку, которая говорит мне шестнадцатеричную информацию о ключах на клавиатуре и объясняет, что представляют собой последние два параметра?

ОБНОВЛЕНИЕ - 1
Использование шпиона ++ Я нахожу эти события, сгенерированные с жму CTRL-S в окне Блокнота

 
1. WM_KEYDOWN nVirtKey:VK_Control, 
2. WM_KEYDOWN nVirtKey:'S' .. some other messates .. 
3. WM_KEYUP nVirtKey:VK_Control. 
4. WM_KEYUP nVirtKey:'S'. 

UPDATE - 2


     private IntPtr startnotepad() { 
      ProcessStartInfo psi = new ProcessStartInfo(); 
      psi.FileName = @"notepad.exe"; 
      String fileName = baseDirectory + textbox1.Text; 
      psi.Arguments = @"""" + fileName + @""""; 
      psi.WindowStyle = ProcessWindowStyle.Minimized; 
      Process p = Process.Start(psi); 
      return p.MainWindowHandle; 
     } 

     private void SaveNotepad(IntPtr handle) 
     { 
      IntPtr handle = GetWindow(handle, 5); // get the keyboard focus handle 
      // verified the handle with Spy ++. 
      SendMessage(handle, 0x0100, 0x11, 0); // keydown ctrl 
      SendMessage(handle, 0x0100, 0x53, 0); // keydown S 
      //SendMessage(handle, 0x0101, 0x11, 0); --- I tried keeping "Keyup Ctrl" here as well. 
      SendMessage(handle, 0x0101, 0x53, 0); // keyup s 
      SendMessage(handle, 0x0101, 0x11, 0); // keyup ctrl    
     } 

Этот код делает не работает (за исключением его части), хотя я могу видеть WM_KEYDOWN - CTRL .. WM_KEYDOWN - 'S' .. KEYUP 'S' и KEYUP CTR L отправляется в правое окно в spy ++. Может кто-нибудь прокомментировать, что не так с этим кодом? Или любые предложения, если я делаю что-то действительно глупое.

UPDATE 3

я должен использовать PostMessage вместо SendMessage, как @Hans предложил в своих комментариях.


[DllImport("user32.dll")] 
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

     private void Save(IntPtr mainWindowHandle) 
     {    
      IntPtr handle = GetWindow(mainWindowHandle, 5); // getChild window 
      IntPtr CTRL_KEY = new IntPtr(0x11); 
      uint KEY_DOWN = 0x0100; 
      uint KEY_UP = 0x0101; 
      IntPtr S_KEY = new IntPtr(0x53); 

      //SetForegroundWindow(p.MainWindowHandle); 
      PostMessage(handle, KEY_DOWN, CTRL_KEY, IntPtr.Zero); 
      PostMessage(handle, KEY_DOWN, S_KEY, IntPtr.Zero); 
      PostMessage(handle, KEY_UP, S_KEY, IntPtr.Zero); 
      PostMessage(handle, KEY_UP, CTRL_KEY, IntPtr.Zero);      
     } 

Вышеупомянутый код вместо CTRL + S отправляет CTRL и S в окно Блокнота. Итак, я вижу два «S», которые бросают в «Блокнот». Глядя на реальное сообщение, сгенерированное при нажатии CTRL + S, я вижу, что последний параметр моего Postmessage неверен. Это должно быть что-то вроде (для клавиши KEY UP CTRL «C01F0001»)

Не могли бы вы рассказать мне, как передать этот шестнадцатеричный как последний параметр postmessage?


// does not work 
PostMessage(handle, KEY_UP, CTRL_KEY, new IntPtr(0xC01F0001); 

Update 4: Я думаю, что мы не можем послать «горячий ключ» сообщения в свернутом окне. используя сообщение.
Этот ниже код работает с SendInput: но он всплывает в окне, какой вид цели. В любом случае, просто хотел обновить эту тему.


private void Save_Notepad(IntPtr mainWindowHandle) { 
      //SetActiveWindow(mainWindowHandle); 
      //SetFocus(GetWindow(mainWindowHandle, 5)); 
      ShowWindow(mainWindowHandle, 1); // show window 
      SetForegroundWindow(mainWindowHandle); 
      //SetActiveWindow(mainWindowHandle); 
      //SetFocus(GetWindow(mainWindowHandle, 5)); 
      //IntPtr returnvalue = SetFocus(mainWindowHandle); 
      uint intReturn; 
      INPUT structInput; 
      structInput = new INPUT(); 
      structInput.type = 1;// keyboard input 
      // key down 
      structInput.ki.wScan = 0x1D; 
      structInput.ki.time = 0; 
      structInput.ki.dwFlags = 0; 
      // key down Ctrl 
      structInput.ki.wVk = 0x11; //0x1D; // 
      intReturn = SendInput(1, ref structInput, Marshal.SizeOf(new INPUT())); 
      // key down S 
      structInput.ki.wScan = 0x1F; 
      structInput.ki.wVk = 0x53; //0x41;//0x53; //0x1F;// 
      intReturn = SendInput(1, ref structInput, Marshal.SizeOf(new INPUT())); 
      // key up 
      structInput.ki.dwFlags = 0x0002; // key up 
      // key up S 
      intReturn = SendInput(1, ref structInput, Marshal.SizeOf(typeof(INPUT))); 
      // key up CTRL 
      structInput.ki.wVk = 0x11; //0x1D; // 
      intReturn = SendInput(1, ref structInput, Marshal.SizeOf(new INPUT())); 
      //ShowWindow(mainWindowHandle, 2); // minimize it again 
     } 

После CTRL + S я могу свести к минимуму окно, но затем создаст вспышку. Может ли кто-нибудь предложить, могу ли я достичь этой функциональности без «FLASH» (по крайней мере)?
UPDATE 5: с помощью WM_SYSCOMMAND


IntPtr handle = GetWindow(mainWindowHandle, 5); 
// send Alt F message to Notepad. 
// http://msdn.microsoft.com/en-us/library/ms646360(v=VS.85).aspx 
// I can see this is working. 
PostMessage(handle, 0x0112, 0xF100, 'f'); // send WM_SYSCOMMAND 
// how to send s on this window ?? 
// I have tried things which I have learned so far. 

мне просто нужно отправлять сообщения S в меню, которое будет всплывал в результате WM_SYSCOMMAND файла. Может ли кто-нибудь указать мне на документацию, как это сделать?


PostMessage(handle, KEY_DOWN, S_KEY, 0x1F0001); // POST does not work 
// tried with mainwindowhandle as well 
PostMessage(handle, 0x111, 'S', 0); // WM_COMMAND does not work 
PostMessage(handle, 0x0112, 0xF100, 's'); // WM_SYSCOMMAND does not work (and does not make sence either) 

Final Update

я не смог отправить^S сообщение в свернутом окне. Я использую sendkeys (^ s) каждые 2-3 секунды, когда основное внимание уделяется редактору.

- Karephul

+0

Что случилось с SendKeys? –

+0

Я имею в виду, ваше обновление 4 очень приятно и все, но разве это не один лайнер с .NET SendKeys? –

+1

Что еще Ганс указал, что вы можете просто отправить «WM_COMMAND», который не будет отображать окно, если оно сведено к минимуму. –

ответ

4

Вы не можете использовать SendMessage (или PostMessage, правильный), чтобы имитировать состояние клавиш модификаторов, как CTRL. Вы должны использовать SendInput().

Такое нажатие клавиши, как Ctrl + S, неточно переводится в сообщение WM_COMMAND. Используйте инструмент Spy ++, чтобы узнать, что происходит, когда вы набираете Ctrl + S вручную. Если вы видите WM_COMMAND, тогда вы золотые, вы можете отправить сообщение SendMessage() для отправки этого сообщения. может использовать. Это, конечно же, будет работать только на конкретном процессе.

+0

Ниже я вижу сообщения в spy ++ в последовательности: 1. WM_KEYDOWN nVirtKey: VK_Control, 2. WM_KEYDOWN nVirtKey: 'S' .. 3 WM_KEYUP nVirtKey: VK_Control. 4. WM_KEYUP nVirtKey: 'S'.
Последовательность немного отличается от того, что я начал думать, но ее на этих линиях. Спасибо за указатели – karephul

+0

Поместите это в свой вопрос, а не в комментарии. Я не вижу WM_COMMAND, используйте SendInput(). –

+0

Я думал, что WM_KEYDOWN - это тип WM_COMMAND. Я рассмотрю SendInput(), который выглядит как что-то, что я могу сделать только в активном окне. Я хочу отправить CTRL S в окно In Active, чтобы пользователь не понимал, что его данные в блокноте сохраняются. – karephul

3

Мне нужно было сделать именно то, что вам нужно сделать, вызвать Ctrl + S в каком-то фоновом окне, после примерно одного дня исследований, похоже, есть много способов добиться этого.

Например нажать Alt-F, то есть 'S' можно назвать:

PostMessage(handle, 0x0112, 0xF100, 0x0046); 
PostMessage(handle, 0x0102, 0x0053, 0); 

Альт-F часть работает на фоне окна, в то время как последующее 'S' не делает.

Другой способ сделать это с WM_COMMAND и WM_MENUSELECT, MF_MOUSESELECT:

IntPtr menu = GetMenu(handle); 
IntPtr subMenu = GetSubMenu(menu, 0);//0 = first menu item 
uint menuItemID = GetMenuItemID(subMenu, 2);//2 = second item in submenu 
SendMessage(handle, 0x0111, 0x20000000 + menuItemID, menu); 

Наконец, несколько иронически решение Simples является вызов WM_COMMAND с menuItemID:

PostMessage(handle, 0x0111, 0x0003, 0x0); 

0x0003 (за исключением в блокноте) определяется приложением и его структурой меню, вы можете получить этот код, прослушивая WM_COMMAND в spy ++ в окне, в то время как вы используете комбинацию комбинационных клавиш или нажмите кнопку мыши в команде меню.

Возможно, вы также можете использовать WM_SYSKEYUP/DOWN и WM_MENUCOMMAND, также такие клавиши, как Ctrl-C, Ctrl-V имеют постоянные определенные значения и могут передаваться как один символ, но только для приложений, которые прослушивают эти жестко закодированные символы. ..

Спасибо за отправную точку.

+0

Почему вы добавляете 0x20000000 в menuItemID? – rodolfoprado

+0

Простите, прошло какое-то время, кажется, я использовал ускоритель с смещением 0x20000000. https://msdn.microsoft.com/en-us/library/windows/desktop/ms647591(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/ windows/desktop/ms647575 (v = vs.85) .aspx – critic

+0

@critic Не могли бы вы объяснить, как вы составили часть «0xF100» для ALT + F ?, чтобы мы могли получить представление о том, как составлять другие композитные нажатия клавиш, например, для пример CTRL + P или любой другой. кто-то еще мог это объяснить? – ElektroStudios

Смежные вопросы