2017-04-13 23 views
1

시스템 트레이에 "표준"아이콘을 사용하는 MFC C++ (관리되지 않는) Windows 응용 프로그램이 있습니다. 이 아이콘은 Visual Studio를 사용하여 편집 된 &이며 VS의 리소스 편집기에 따라 4 비트 색상 만있는 32x32 픽셀입니다.Windows 시스템에 텍스트를 쓸 때 투명성을 유지하는 방법 관리되지 않는 C 프로그램의 트레이 아이콘

Visual Studio에서 투명한 배경 ("이전"이미지에 흰색으로 표시됨)도 설정합니다.

아이콘 위에 2 자리 (1-99)를 쓰면 동적으로 아이콘을 변경하고 싶습니다.

아래의 코드 (이 질문의 내용을 기반으로 : How to draw text with transparency using GDI?)를 사용하여 아이콘에 노란색 "55"를 겹쳐서 표시하면 투명도가 사라지는 것을 제외하면 작동합니다 ("후"이미지에서 검은 색으로 나타남 ). 시스템 트레이). 내 실제 코드는 글꼴 크기 (20), 글꼴 이름 (Courier New), 텍스트 색상 (노란색 - RGB (255, 255, 0)) 및 숫자 값 (55)이 런타임 변수가 아니라는 점에서 매우 약간 다릅니다 고정 값보다.

시스템 트레이가 기꺼이 받아 들여지는 한 배경을 투명하게 유지하는 방법에 대한 제안 사항.

이러한 이미지는 MS 그림판에서 열어 본 이미지를 MS의 Snipping 도구를 사용하여 캡처 한 것으로, 32x32 아이콘은 그대로있는 그대로 표시되지 않습니다.

Before Image

이미지 후 : 이미지 전에

After image

코드 :

void CreateNewIcon(HICON &hNewIcon, HICON hBackgroundIcon) 
{ 
    ::DestroyIcon(hNewIcon); 

    // First create font 
    LOGFONT lf = { 0 }; 
    lf.lfHeight = -20; 
    lf.lfWeight = FW_BOLD; 
    lf.lfOutPrecision = OUT_TT_PRECIS; 
    lf.lfQuality = CLEARTYPE_QUALITY; 
    wmemset(lf.lfFaceName, 0, LF_FACESIZE); 
    lstrcpy(lf.lfFaceName, L"Courier New"); 

    HFONT hFont = ::CreateFontIndirect(&lf); 

    ICONINFO ii = { 0 }; 
    ::GetIconInfo(hBackgroundIcon, &ii); 

    BITMAP bm = { 0 }; 
    ::GetObject(ii.hbmColor, sizeof(bm), &bm); 
    SIZE szBmp = { bm.bmWidth, bm.bmHeight }; 

    HDC hDc = ::GetDC(NULL); 
    HDC hMemDC = ::CreateCompatibleDC(hDc); 

    HGDIOBJ hOldBmp = ::SelectObject(hMemDC, ii.hbmColor); 
    HGDIOBJ hOldFont = ::SelectObject(hMemDC, hFont); 

    ::SetBkMode(hMemDC, TRANSPARENT); 
    ::SetTextColor(hMemDC, RGB(255, 255, 0)); 
    ::TextOut(hMemDC, 0, 8, L"55", 2); 

    ::SelectObject(hMemDC, hOldFont); 
    ::SelectObject(hMemDC, hOldBmp); 

    // We need a simple mask bitmap for the icon 
    HBITMAP hBmpMsk = ::CreateBitmap(szBmp.cx, szBmp.cy, 1, 1, NULL); 

    ICONINFO ii2 = { 0 }; 
    ii2.fIcon = TRUE; 
    ii2.hbmColor = ii.hbmColor; 
    ii2.hbmMask = hBmpMsk; 

    // Create updated icon 
    hNewIcon = ::CreateIconIndirect(&ii2); 

    // Cleanup 
    ::DeleteObject(hBmpMsk); 
    ::DeleteDC(hMemDC); 
    ::ReleaseDC(NULL, hDc); 
    ::DeleteObject(ii.hbmColor); 
    ::DeleteObject(ii.hbmMask); 
    ::DeleteObject(hFont); 
} 

답변

0

우리의 코드에 여러 가지 문제가 있습니다 :

  • 투명 아이콘 부분에 일반 텍스트 품질의 텍스트를 그리려합니다. 그러나 cleartype 글꼴 렌더링은 배경색을 검사해야하기 때문에 불투명 한 배경 위에 수행해야합니다. 따라서 Anitialiased 품질 (또는 안티 앨리어싱 품질이 아님)으로 전환하거나 텍스트에 불투명 한 배경을 제공해야합니다.
  • hBmpMskyou skip it's content initialization by supplying NULL for bits pointer을 만들면 결과 아이콘의 투명도가 완전히 떨어집니다. 이 마스크 비트 매트를 적절하게 채워야합니다.

단색 비트 맵 마스크가 안티 앨리어싱 된 텍스트의 반투명 부분을 처리 할 수 ​​없으므로 더 높은 비트 깊이로 전환해야 할 수도 있습니다.

갱신

난 당신이 클리어 텍스트를 그릴 수 있지만 불투명 한 배경으로, 다음 GetTextExtentPoint32 같은 것을 사용하여 텍스트 사각형을 얻을, 다음 hBmpMsk로 원래 비트 맵 마스크에서 데이터를 복사 한 다음 마지막으로 흰색 (텍스트)을 작성해야합니다 생각 새 아이콘은 원본에서 투명도를 유지하고 불투명 한 텍스트 블록을 갖습니다.

+0

, 나는 클리어 타입 글꼴을 필요가 없습니다 그래서 지금은 "lf.lfOutPrecision"와 "lf.lfQuality"모두를 commentted있다. 하지만 어떻게하면이 마스크 비트 맵을 적절하게 채울 수 있습니까? – DDK

+0

실제로 트레이 아이콘 크기는 시스템 설정에 따라 다르며 [GetSystemMetrics with SM_CXSMICON 및 SM_CYSMICON] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385 (v) = vs.85) .aspx). 'lf.lfQuality'를 주석 처리하는 것은 그것이 DEFAULT_QUALITY (0)를 포함하게 만들지 만, 반드시 cleartype을 의미하지는 않습니다. 어쨌든, 나는 주석 공간이 부족하기 때문에 원래의 대답을 편집했습니다. – VTT

+0

정확히 무엇을 제안하고 있는지 모르겠으므로 수정할 템플릿 코드가있을 수 있습니까? 아이콘 크기에 관해서는,이 응용 프로그램은 현재 시스템 트레이 아이콘으로 XP에서 W10까지 수년간 실행되어 왔으며 런타임에 수정하는 중이므로 현재 크기로 유지할 것입니다. 또한이 기능이 32x32에서 작동하면이를 바꿀 수도 있습니다. 방금 테스트되었습니다 : SM_CXICON = 32 및 SM_CXSMICON = 16. – DDK

0

VTT의 도움을 받아 주셔서 감사합니다. 이것은 나를 위해 작동하는 것 같습니다.품질 (32 × 32)이 작은 아이콘으로

void CreateNewIcon(HICON &hNewIcon, HICON hBackgroundIcon) 
{ 
    ::DestroyIcon(hNewIcon); 

    HDC hDc = ::GetDC(NULL); 
    HDC hMemDC = ::CreateCompatibleDC(hDc); 

    // Load up background icon 
    ICONINFO ii = { 0 }; 
    ::GetIconInfo(hBackgroundIcon, &ii); 

    HGDIOBJ hOldBmp = ::SelectObject(hMemDC, ii.hbmColor); 

    // Create font 
    LOGFONT lf = { 0 }; 
    lf.lfHeight = -20; 
    lf.lfWeight = FW_BOLD; 
    lf.lfOutPrecision = OUT_TT_PRECIS; 
    lf.lfQuality = ANTIALIASED_QUALITY; 
    wmemset(lf.lfFaceName, 0, LF_FACESIZE); 
    lstrcpy(lf.lfFaceName, L"Courier New"); 

    HFONT hFont = ::CreateFontIndirect(&lf); 
    HGDIOBJ hOldFont = ::SelectObject(hMemDC, hFont); 

    // Write text 
    ::SetBkMode(hMemDC, TRANSPARENT); 
    ::SetTextColor(hMemDC, RGB(255, 255, 0)); 
    ::TextOut(hMemDC, 0, 8, L"55", 2); 

    // Set up mask 
    HDC hMaskDC = ::CreateCompatibleDC(hDc); 
    HGDIOBJ hOldMaskBmp = ::SelectObject(hMaskDC, ii.hbmMask); 

    // Also write text on here 
    HGDIOBJ hOldMaskFont = ::SelectObject(hMaskDC, hFont); 
    ::SetBkMode(hMaskDC, TRANSPARENT); 
    ::SetTextColor(hMaskDC, RGB(255, 255, 0)); 
    ::TextOut(hMaskDC, 0, 8, L"55", 2); 

    // Get handle to create mask bitmap 
    HBITMAP hMaskBmp = (HBITMAP)::SelectObject(hMaskDC, hOldMaskBmp); 

    // Use new icon bitmap with text and new mask bitmap with text 
    ICONINFO ii2 = { 0 }; 
    ii2.fIcon = TRUE; 
    ii2.hbmMask = hMaskBmp; 
    ii2.hbmColor = ii.hbmColor; 

    // Create updated icon 
    hNewIcon = ::CreateIconIndirect(&ii2); 

    // Cleanup bitmap mask 
    ::DeleteObject(hMaskBmp); 
    ::DeleteDC(hMaskDC); 

    // Cleanup font 
    ::SelectObject(hMaskDC, hOldMaskFont); 
    ::SelectObject(hMemDC, hOldFont); 
    ::DeleteObject(hFont); 

    // Release background bitmap 
    ::SelectObject(hMemDC, hOldBmp); 

    // Delete background icon bitmap info 
    ::DeleteObject(ii.hbmColor); 
    ::DeleteObject(ii.hbmMask); 

    ::DeleteDC(hMemDC); 
    ::ReleaseDC(NULL, hDc); 
}