2012-11-14 27 views
5

Tôi đang vẽ văn bản thành một phần bitmap DIB có màn hình ngoài, sâu 32 bit và sử dụng kênh alpha (ARGB). Tôi vẽ điểm ảnh trực tiếp vào bộ nhớ. Sau đó, tôi tạo ra một đối tượng đồ họa Gdiplus, chuyển bộ nhớ DC của tôi cho nó, và vẽ văn bản bằng cách sử dụng Graphics :: DrawString. Điều này hoạt động tốt trong những hoàn cảnh bình thường. Tuy nhiên, trên Remote Desktop, văn bản được hiển thị hoàn toàn trong suốt, tức là thay vì vẽ bất kỳ pixel màu nào, bạn có thể xem qua văn bản ở đâu. Có ai biết tại sao điều này là như vậy, và làm thế nào để sửa chữa nó ??Gdiplus DrawString lấy văn bản trong suốt trên Máy để bàn Từ xa

Dưới đây là thói quen drawString tôi:

void SplashScreen::drawString (MyString &ivText, Gdiplus::RectF &r, 
    Gdiplus::ARGB c, Gdiplus::StringAlignment align, Gdiplus::Font &fnt, 
    Gdiplus::Graphics &gfx) 
    { 
    Gdiplus::StringFormat fmt; 
    fmt.SetAlignment (align); 
    Gdiplus::SolidBrush brush (c); 
    wchar_t *wstr = new wchar_t [ivText.length()+1]; 
    std::mbstowcs (wstr, ivText.cstr(), ivText.length()+1); 
    gfx.DrawString (wstr, ivText.length(), &fnt, r, &fmt, &brush); 
    delete wstr; 
    } 

Và đó là cách tôi tạo DIB:

BITMAPV5HEADER bhd; 
memset (&bhd, 0, sizeof (bhd)); 
bhd.bV5Size = sizeof (BITMAPV5HEADER); 
bhd.bV5Width = nWidth; 
bhd.bV5Height = -nHeight; // negative height indicates top-down DIB 
bhd.bV5Planes = 1; 
bhd.bV5BitCount = 32; 
bhd.bV5Compression = BI_BITFIELDS; 
bhd.bV5RedMask = 0x00FF0000; 
bhd.bV5GreenMask = 0x0000FF00; 
bhd.bV5BlueMask = 0x000000FF; 
bhd.bV5AlphaMask = 0xFF000000; 
m_pBuf = NULL; 
m_hBmp = ::CreateDIBSection (m_hDC, (BITMAPINFO *) &bhd, DIB_RGB_COLORS, 
    (void **) &m_pBuf, NULL, 0); 
if (m_hBmp == NULL || m_pBuf == NULL) 
    { 
    // error... 
    } 
HGDIOBJ oldObj = ::SelectObject (m_hDC, m_hBmp); 
if (oldObj == NULL) 
    { 
    // error... 
    } 

Sau khi vẽ văn bản vào DIB, tôi làm

gfx.Flush (Gdiplus::FlushIntentionSync); 

EDIT: Nó cũng có thể được bạn quan tâm rằng cửa sổ nơi DIB cuối cùng được đưa vào là một cửa sổ WS_EX_LAYERED. Đó là màn hình giật gân hiển thị khi ứng dụng bắt đầu và bị từ từ nhạt dần vào và ra bằng bộ hẹn giờ và phương pháp sau:

void SplashScreen::setWindowTransparency (int nAlpha) 
    // @param nAlpha: 255 is opaque, 0 is fully transparent. 
    { 
    HWND hwnd = getHwnd(); 
    BLENDFUNCTION blend; 
    blend.BlendOp = AC_SRC_OVER; 
    blend.BlendFlags = 0; 
    blend.SourceConstantAlpha = nAlpha; 
    blend.AlphaFormat = AC_SRC_ALPHA; 
    BOOL bResult = ::UpdateLayeredWindow (hwnd, NULL, NULL, NULL, NULL, 
    NULL, RGB (0, 0, 0), &blend, ULW_ALPHA); 
    } 
+0

Điều gì sẽ xảy ra khi bạn thay đổi cài đặt độ sâu màu của phiên RDP? –

+0

Tôi đã thử nghiệm 15bit, 16bit, 24bit, 32bit (thiết lập trong tab Hiển thị trước khi phiên RDP được bắt đầu). Cùng một vấn đề với tất cả các cài đặt này. (Trên thực tế, 32bit không nhìn 32 bit với tôi. Có lẽ RDP là gian lận?) –

+0

Làm thế nào để vô hiệu hóa Bitmap Caching Persistent? –

Trả lời

3

Tôi ngạc nhiên về công việc này. Vẽ bằng gdi32 mất thông tin alpha và khi tôi hiểu nó, bất kỳ bản vẽ nào trên DIB 32 bit có gdi32 đều để lại thông tin alpha trong DIB không xác định. GDI + phải trải qua gdi32 trong trường hợp này bởi vì bạn đã cho nó một HDC. Để vẽ đến DIB RGBA bằng GDI +, bạn cần tạo đối tượng bitmap GDI + được hỗ trợ bởi bộ nhớ DIB của bạn với định dạng pixel chính xác (sử dụng một hàm tạo con trỏ dữ liệu pixel, chẳng hạn như this one), sau đó create a Graphics object from your Bitmap. Điều này cho phép GDI + vẽ trực tiếp vào bộ nhớ của DIB và xử lý kênh alpha đúng hơn là đi qua gdi32.

Tất nhiên, nếu bạn không cần alpha mỗi pixel, bạn có thể đơn giản hóa mọi thứ bằng cách sử dụng AlphaFormat 0 trong hàm pha trộn của bạn để bỏ qua kênh alpha trong DIB của bạn.

+0

Đây có thể là câu trả lời, nhưng kể từ khi tôi làm điều này chỉ cho màn hình Splash lúc khởi động ứng dụng, tôi "giải quyết" vấn đề bằng cách đơn giản phát hiện nếu ứng dụng đang chạy dưới Remote Desktop, và nếu vậy, không hiển thị màn hình Splash ở tất cả ... Giá rẻ, tôi biết. –

0

Tôi có giải pháp khả thi cho bạn. Không chắc bạn đang kết nối phiên bản Windows nào, nhưng trên máy tính từ xa, bạn có thể phải bật chế độ màu 32 bit cho các dịch vụ đầu cuối. Nếu không, máy khách của bạn có thể bị giới hạn ở chế độ 16 bit.

Trên máy chủ, sử dụng gpedit.msc, định cấu hình tùy chọn "Giới hạn độ sâu màu tối đa" thành 32 bit. Trong Windows 2008/2012, điều này nằm trong Administrative Templates - Windows Components - Remote Desktop Services - Remote Session Environment.

Nếu bạn đang kết nối với máy tính Windows XP/Vista/7/8, tôi không chắc liệu cài đặt gpedit này có khả dụng hay không.

+0

Tất nhiên tôi không thể làm điều này, bởi vì tôi không phải là người dùng duy nhất của ứng dụng của chúng tôi. Tôi không thể mong đợi người dùng thay đổi cài đặt của họ trong Remote Desktop. Thay vào đó, ứng dụng phải hoạt động trong cả hai môi trường. –

Các vấn đề liên quan