2011-02-28 15 views
3

C# 코드를 사용하여 TextPad 창을 저장하려고합니다. 창 핸들을 찾을 수 있지만 Ctrl + S를 해당 창에 보내는 방법을 모르겠습니다. 이를 위해 P/Invoke API를 사용하고 싶습니다. 또한 해당 시간에 응용 프로그램이 활성화되기 때문에 TextPad 창이 비활성화됩니다. CTRL-S 메시지를 창에 보냅니다.

Send Ctrl+Up to a window

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

나는 내 문제와 매우 유사하다이 토론 바라 보았다. 나는

  • 에서 KeyDown CTRL 키
  • 에서 KeyDown S 키
  • 의 keyup S 키
  • 의 keyup CTRL 키

나는 확실하지 않다 아래와 같은 메시지를 보낼 수 4 할 필요가 있음을 논리적으로 이해 올바른 매개 변수를 SendMessage로 보내는 방법. 사용하는 창을 닫으려면

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

나는 MSDN 라이브러리에서 가져 왔습니다.

키보드의 키에 대한 16 진수를 알려주고 마지막 두 매개 변수가 나타내는 내용을 설명하는 링크로 안내해주십시오.

UPDATE - 스파이를 사용하여 1
++ 나는 메모장 창에 CTRL-S를 누르면 생성이 이벤트를 찾을 UPDATE가

 
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'. 

-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 ++에서 오른쪽 창으로 보내집니다. 누구든지이 코드에 어떤 문제가 있다고 말할 수 있습니까? 또는 나가 진짜로 어리석은 무언가를하는 경우에 어떤 제안. @Hans 자신의 의견 제안 내가 SendMessage 대신 PostMessage를을 사용해야 3

UPDATE.


[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의 마지막 매개 변수로이 16 진수를 전달하는 방법을 알려주시겠습니까?


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

업데이트 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의 결과로 나타납니다 메뉴를 제출 S 메시지를 보낼 필요가

 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. 

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) 

최종 업데이트

난 최소화 된 창으로^S 메시지를 보낼 수 없습니다. 포커스가 편집기에있을 때마다 2 ~ 3 초마다 sendkeys (^ s)를 사용하고 있습니다.

- Karephul

+0

SendKeys의 문제점은 무엇입니까? –

+0

귀하의 업데이트 4는 매우 훌륭하지만 .NET SendKeys의 라이너가 아닙니다. –

+1

더 많은 것 한스는 단지 WM_COMMAND를 보내면 윈도우가 최소화되어있는 것을 보지 못하게 할 수 있다고 지적했다. –

답변

4

당신은 CTRL처럼 수식 키의 상태를 시뮬레이션 할 수 sendMessage 첨부 (또는 PostMessage를, 올바른)를 사용할 수 없습니다. SendInput()을 사용해야합니다.

Ctrl + S와 같은 키 입력은 일반적으로 WM_COMMAND 메시지로 변환되지 않습니다. Ctrl + S를 직접 입력하면 Spy ++ 도구를 사용하여 어떤 일이 발생하는지 확인할 수 있습니다. 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()을 살펴볼 것입니다 - Active Window에서만 할 수있는 것처럼 보입니다. CTRL S를 In Active 창에 보내고 싶습니다. 그래서 사용자는 자신의 메모장 데이터가 저장되고 있다는 것을 알지 못합니다. – karephul

3

당신이해야 할 일을 정확히 수행 할 필요가있었습니다. 배경 화면에서 Ctrl + S를 부르십시오. 약 하루가 지나면 이것을 달성하는 방법이 많이 있습니다. 다음, 'S'를 Alt 키-F를 눌러 예를 들어

당신이 호출 할 수 있습니다 : 이후의 'S'는하지 않지만

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

에서 Alt-F 부분은, 배경 창에서 작동합니다.

이 일을하는 또 다른 방법은 WM_COMMAND 및 WM_MENUSELECT, MF_MOUSESELECT 함께 :

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

0x0003 (저장 :

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); 

마지막으로 다소 반어 가장 단순한 해결책은 메뉴 항목 id와 WM_COMMAND를 호출하는 것입니다 메모장에서) 응용 프로그램과 그것의 메뉴 구조에 의해 결정되면, 당신은 콤보 키 조합을 사용하거나 메뉴 명령에서 마우스 버튼을 누르는 동안 윈도우의 spy ++에서 WM_COMMAND를 듣고이 코드를 얻을 수 있습니다.

WM_SYSKEYUP/DOWN 및 WM_MENUCOMMAND를 사용할 수도 있으며 Ctrl-C, Ctrl-V와 같은 키는 상수로 정의 된 값을 가지며 한 문자로 전달할 수 있지만이 하드 코드 된 문자를 수신하는 앱에만 전달할 수 있습니다. ..

출발점 주셔서 감사합니다.

+0

왜 menuItemID에 0x20000000을 추가하고 있습니까? – 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 ALT + F에 대해 "0xF100"부분을 작성한 방법을 설명해 주실 수 있으니, 다음과 같은 다른 합성 키 입력을 작성하는 방법에 대한 아이디어를 얻을 수 있습니다. CTRL + P 또는 다른 어떤 것. 다른 사람이 설명 할 수 있니?. – ElektroStudios

관련 문제