2011-01-14 72 views
1

我正在寫一個簡單的Windows窗體實用程序來截屏整個屏幕或活動窗口並保存文件。該winform有一個名爲'Capture'的按鈕,點擊後會截取屏幕截圖。PrintScreen only active window

我的代碼完全適用於整個屏幕,但無法找出活動窗口。

通過我當前的代碼,如果我選擇「活動窗口」,它會結束Print Screening應用程序本身,這不是我想要的。

這裏是我的代碼(Capture_Click方法下):

try 
     { 
      this.Hide(); 

      bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb); 
      //bmpScreenshot = new Bitmap(this.Bounds.Width, this.Bounds.Height, PixelFormat.Format32bppArgb); 

      gfxScreenshot = Graphics.FromImage(bmpScreenshot); 

      if (AltPrint.Checked) 
      { 
       gfxScreenshot.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size, CopyPixelOperation.SourceCopy); 
      } 
      else 
      { 
       gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy); 
      } 

      bmpScreenshot.Save(SaveLocation, ImageFormat.Png); 

      number++; 
     } 
+0

你重建`PrintScreen`和'ALT + PrintScreen` *按鍵*? – 2011-01-14 15:13:09

+0

「select active window」是什麼意思?你如何選擇它? – Nobody 2011-01-14 15:14:35

+0

@奧斯汀:不,我的winform有一個名爲Capture的按鈕。點擊它,截圖。上面粘貼的代碼位於button_Click方法中。 – xbonez 2011-01-14 15:18:44

回答

1

至於我可以看到你的代碼使用它自己的形式的界限捕捉「活動」窗口。這可能不是你想要的。

如果你想用鼠標「打印」一個窗口(而不是熱鍵,這可能更容易實現),你需要能夠從你自己的窗體讓用戶指向另一個窗口捕捉。這裏是一個想法,描述如何做到這一點:

  1. 當用戶按下「捕獲」按鈕捕獲鼠標並啓動拖動操作。
  2. 讓用戶拖動鼠標(可能現在有一個「靶心」或「相機」光標)到要捕獲的窗口。
  3. 當用戶釋放鼠標確定窗口位於頂部並使用此窗口的位置和大小捕獲正確的像素。

您可能需要使用P/Invoke來獲取有關桌面上所有頂級窗口的信息。

請注意,「鼠標捕捉」與「屏幕捕捉」有很大不同。當應用程序「捕獲鼠標」時,它將佔用鼠標光標的所有權,並且無​​法追蹤鼠標,即使它移動到應用程序窗口邊界之外。

0

您需要借用市售屏幕捕獲應用程序,如PSP的設計。我認爲你需要使用'熱門'鍵來觸發活動窗口的捕獲。而不是在Capture_Click事件上進行。這樣,您可以隱藏應用程序的窗口,使其不會成爲活動窗口。然後,當用戶按下「熱門」鍵時,您可以捕捉它。

0

SendKeys怎麼樣?

Windows.Forms.SendKeys.Send("%{PRTSC}"); 

它會將當前選定的窗口複製到剪貼板對象。

比調用

BitmapSource image = Clipboard.GetImage(); 

,你可以得到你的形象回到

1

你的意見似乎明白,一旦你的應用程序獲得焦點(當你點擊它),另一個應用程序已經失去了它,不再是「活躍」。

可能的替代方案:您的應用程序獲得焦點時會收到WM_SETFOCUS消息。該消息的wParam是一個窗口放在焦點上的句柄 - 該窗口屬於你想要捕捉的應用程序。

當然,該窗口只會是一個子窗口或控件,但您可以確定哪個應用程序擁有該按鈕。

2

在你的button_Click方法中,爲了捕獲除捕獲的窗口以外的窗口,唯一可行的方法是使用Windows API的user32

你首先需要平臺調用一些像這樣的方法:

[DllImport("user32.dll", SetLastError = true)] 
private static extern int GetWindowLong(IntPtr hWnd, GetWindowLongNIndex nIndex); 

我建議www.pinvoke.net/有關此更多信息。

這是我自己的Window類(工作正在進行中,但可用的),它歡迎您作爲一個例子來使用:在那裏http://pastebin.com/fj2tEaPY

一些有用的屬性,你是:

  • 得到AllWindows
  • 得到TaskbarWindows
  • 設置ForegroundWindow

您需要獲取當前窗口的句柄(使用獲得ForegroundWindow,然後Handle屬性),然後找到想要捕獲圖像的窗口,可能使用類似於TaskbarWindows中的代碼。一旦你有了這個窗口,你將需要發送按鍵Alt + PrtScn(也許可以使用user32 API,但我不會進入它。)然後使用靜態ForegroundWindow屬性將orignal窗口設置爲使用句柄的forground你在開始時保存的。

祝你好運!

1

我最終採取了不同的路線。

我允許用戶調整我的表單窗口的大小以精確地覆蓋他們需要截圖的區域,然後當他們單擊按鈕時,表單隱藏自身,截取它覆蓋的區域並再次出現。與我最初的計劃相反,我相信這會更有益,因爲我的目標用戶(我在超頻論壇的朋友)很少截取一個窗口的截圖。他們大多需要覆蓋幾個窗口(溫度監控,時鐘速度監控,穩定性測試等)。

感謝所有的答案傢伙。他們肯定讓我思考,並讓我意識到我的選擇是什麼。

如果其他人需要它,這是我使用的是僅捕獲屏幕的部分按鈕的代碼:

 try 
     { 
      this.Hide(); 
      Thread.Sleep(250); 

      bmpScreenshot = new Bitmap(this.Bounds.Width, this.Bounds.Height, PixelFormat.Format32bppArgb); 

      gfxScreenshot = Graphics.FromImage(bmpScreenshot); 

      gfxScreenshot.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size, CopyPixelOperation.SourceCopy); 

      bmpScreenshot.Save(SaveLocation, ImageFormat.Png); 

      tbxStatus.AppendText(Environment.NewLine); 
      tbxStatus.AppendText(Environment.NewLine); 
      tbxStatus.AppendText("Screenshot saved at " + SaveLocation); 

      numSuffix++; 
     } 
     catch (Exception ex) 
     { 
      tbxStatus.AppendText(Environment.NewLine); 
      tbxStatus.AppendText(Environment.NewLine); 
      tbxStatus.AppendText("Unable to take screenshot. Exception: " + ex.ToString()); 
     } 
     finally 
     { 
      this.Show(); 
     }