2010-10-19 244 views
6

我正在用C++編寫Qt4中的屏幕捕獲應用程序。在雙屏幕上調整時遇到問題。第二個屏幕無法顯示圖像。我嘗試了一個C#應用程序,它將抓取所有桌面上的圖像,我可以從那裏提取每個屏幕桌面圖像。 這裏是C#代碼使用Qt4捕獲多個屏幕桌面圖像

using System; 
using System.Drawing; 
using System.Runtime.InteropServices; 

public class TestGrab 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
    IntPtr hDC = WindowsNative.GetDC(WindowsNative.GetDesktopWindow()); 
    IntPtr hBitmap = WindowsNative.GetCurrentObject(hDC, 
    WindowsNative.OBJ_BITMAP); 
    System.Drawing.Bitmap imageDesktop = System.Drawing.Image.FromHbitmap(
    hBitmap); 
    imageDesktop.Save(@"c:\zzzzdesktop.png"); 
    } 
} 

public class WindowsNative 
{ 
    [DllImport("user32.dll")] 
    public static extern IntPtr GetDesktopWindow(); 

    [DllImport("user32.dll")] 
    public static extern IntPtr GetDC(IntPtr ptr); 

    public const int OBJ_BITMAP = 7; 
    [DllImport("gdi32.dll")] 
    public static extern IntPtr GetCurrentObject(IntPtr hdc, uint 
    uiObjectType); 
} 

Qt的代碼較小,也我測試如果本地窗口處理對桌面是從Qt的desktop0> winId(),但它們是相等的

QPixmap CaptureWinDesktop() 
{ 
    WId desktop=GetDesktopWindow(); 
    WId desktop2=QApplication::desktop()->winId(); 
    if(desktop!=desktop2) 
    { 
     qDebug("sunt fdiferite WId"); 
    } 
    QPixmap entireDesktop= QPixmap::grabWindow(desktop); 
    return entireDesktop; 
} 
不同

我不確定這是否是Qt中的錯誤,或者是一個功能,使用相同的窗口句柄時,它只會重試第一個桌面,實際上它是由2個屏幕組成的桌面。一個想法是使用本機窗口調用並將圖像保存在臨時文件中,然後從那裏加載QPixmap,但這並不是簡單的將HBITMAP保存在沒有MFC的C++文件中。 結論:您認爲Qt中的錯誤是什麼?任何想法如何解決它(沒有MFC)

+0

我還發現了一個使用GDI http://www.experts-exchange的例子。com/Microsoft/Development/Q_26484815.html,看底部,數字是硬編碼的,所以你必須得到尺寸並修改代碼 – simion314 2010-10-19 14:18:43

回答

3

我最近注意到了同樣的問題。

我最終決定放棄截圖的Qt。 Qt中斷的另一個情況是使用Windows Vista或Windows 7的Aero主題。這個主題顯然將所有數據都渲染到後臺緩衝區中,所以Qt拍攝的所有屏幕截圖都是黑屏。

而是使用Qt作爲http://www.apriorit.com/our-experience/articles/9-sd-articles/193-multi-monitor-screenshot

+0

Thx,這可以節省我所有的HDC,RECT HBITMAP和其他複雜結構 – simion314 2010-10-19 14:09:24

+0

如果你的應用程序是開源的,我希望看到代碼,在我看來,你鏈接的截圖應用程序使用MFC atlimage.h – simion314 2010-10-21 11:47:10

4

描述你可以用QDesktopWidget::screenCount()(QT 4.6)計算的屏幕,然後通過所有屏幕旅行,做QPixmap::grabWindow(...)

關於「桌面組成,我可以推薦使用ScreenShooter類從2個屏幕「。這一切都取決於2個屏幕是否爲虛擬(所有屏幕均視爲一個屏幕)或不。

@Frerich Raabe:它適用於Windows 7,因爲我使用類似的代碼來執行屏幕抓取。

+0

:即使我使用grabWindow(...)也會返回第一個屏幕第二個屏幕。你確定它可以在雙顯示器上工作嗎? – simion314 2010-10-19 14:13:12

+0

我最近正在實現抓屏功能,是的它工作正常。你使用的是什麼Qt版本? – 2010-10-19 16:48:46

+0

我在Windows XP sp3上使用4.6.3,我已經安裝了雙顯示器,並且我總是隻能獲得第一個scree,而且我嘗試了所有的可能性,我不喜歡使用win APIDS – simion314 2010-10-19 18:43:17

2

對於虛擬桌面,QPixmap::grabWindow方法似乎會返回主屏幕大小的屏幕截圖。傳遞完整虛擬桌面的尺寸將返回兩個顯示器的屏幕截圖;

QDesktopWidget *desktop = QApplication::desktop(); 
    QPixmap screenshot = QPixmap::grabWindow(desktop->winId(), 0, 0, desktop->width(), desktop->height()); 

還沒有測試在Unix/Mac的框這種行爲,但它的工作原理的Windows 7

+0

在我的Ubuntu 10.10上像魅力一樣工作!非常感謝您告訴我路徑。 – zeFree 2013-10-16 17:45:42

0

在Windows上的多顯示器設置下,這些顯示器通常被加入到一個虛擬桌面。我說「通常」是因爲我不完全確定從XP SP0(2001年10月25日)到Win8 SP0(2012年10月26日)的所有Windows版本會發生什麼情況。但是,作爲虛擬桌面,這意味着screen(x)將始終返回相同的小部件;從我看到的這是唯一的QDesktopWidget本身。但是,screenGeometry(x)將爲每個枚舉的監視器返回不同的值。

您可以通過使用screenGeometry(x)的結果作爲QPixmap :: grabWindow的參數來抓取第二個屏幕;即:

QDesktopWidget* desktop = QApplication::desktop(); 
WId wid = desktop->winId(); 
QRect geo = desktop->screenGeometry(indexOfTheMonitorYouWant); 
QPixmap cap = QPixmap::grabWindow(wid, geo.left(), geo.top(), geo.width(), geo.height()); 

這現在正在爲我工​​作,而且我將把構建交給我的QA團隊。