title: Sending CTRL-S message to a window
body: <p>I want to save a TextPad window using C# code; I can find out the handle of the window but not sure how to send CTRL - S to that window. I want to use P/Invoke API to achieve this. Also, that TextPad window will be inactive, because my application will be active at that time.</p>
  
  <pre><code>[DllImport("user32.dll")]
  private static extern int SendMessage(IntPtr hwnd, int msg, int wParam, int lParam);
  </code></pre>
  
  <p><a href="https://stackoverflow.com/questions/2745669/send-ctrlup-to-a-window">Send Ctrl+Up to a window</a></p>
  
  <p>I looked at this discussion which is very similar to my problem. I understand logically that I have to do 4 send messages like below</p>
  
  <ul>
  <li>KeyDown CTRL key</li>
  <li>KeyDown S key</li>
  <li>KeyUp S key</li>
  <li>KeyUp CTRL key</li>
  </ul>
  
  <p>I am not sure how to send the right parameters to the SendMessage. To close the window I use </p>
  
  <pre><code>SendMessage(hWnd, 0x0010, 0, 0);
  </code></pre>
  
  <p>I got this from MSDN library.</p>
  
  <p>Can you please direct me to some link which tells me the hexadecimal for keys in the keyboard and explains what the last two parameters represent?</p>
  
  <p><b> UPDATE - 1 </b> <br />
  Using spy++ I find these events generated with I press CTRL-S on Notepad window</p>
  
  <pre>
  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'. 
  </pre>
  
  <p><b> UPDATE - 2 </b> <br /></p>
  
  <pre><code>
         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            
          }
  </code></pre>
  
  <p>This code does not work (save part of it) even though I am able to see the WM_KEYDOWN - CTRL .. WM_KEYDOWN - 'S' .. KEYUP 'S' and KEYUP CTRL being sent to the right window in spy++. Can anyone comment what is wrong with this code? Or any suggestions if I am doing something really stupid.</p>
  
  <p><b> UPDATE 3 </b></p>
  
  <p>I should be using PostMessage instead of SendMessage as @Hans suggested in his comments. </p>
  
  <pre><code>
   [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);                      
          } 
  
  </code></pre>
  
  <p>The above code instead of CTRL+S sends CTRL and S to Notepad window. So, I can see two "S" being thrown at Notepad. Looking at the real message generated when we press CTRL+S, I see that last parameter of my Postmessage is wrong. It should be something like (for KEY UP CTRL key "C01F0001")</p>
  
  <p>Can you please tell me how to pass this hexadecimal as last parameter of postmessage? </p>
  
  <pre><code>
  // does not work
  PostMessage(handle, KEY_UP, CTRL_KEY, new IntPtr(0xC01F0001);
  </code></pre>
  
  <p><b>
  Update 4 : I think we cannot send "hot key" messages to a minimized window. using Post Message.
  <br />
   </b>
  This below code works with SendInput: but it will pop up the window, which kind a mar the purpose. Anyways, just wanted to update this thread.</p>
  
  <pre><code>
   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 
          }
  </code></pre>
  
  <p>After CTRL + S I can minimize the window but then it will create a flash.
  Can anyone suggest if I can achieve this functionality without the "FLASH" (at least)?
  <br />
  
  <b> UPDATE 5 : using WM_SYSCOMMAND</b></p>
  
  <pre><code>
  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. 
  </code></pre>
  
  <p>I just need to send S messages to file menu which will pop up as a result of WM_SYSCOMMAND. Can anyone point me to a documentation to how to do that?</p>
  
  <pre><code>
  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)
  
  </code></pre>
  
  <p><b>Final Update</b></p>
  
  <p>I was not able to send ^S message to a minimized window. I am using sendkeys(^s) every 2-3 seconds when the focus is on an editor. </p>
  
  <p>-- Karephul</p>