#c #windows #winapi #mfc
#c #Windows #winapi #mfc
Вопрос:
Я создаю пошаговое руководство с новым пользовательским интерфейсом для своего приложения MFC и хочу выделить определенные элементы управления по мере прохождения пошагового руководства. В частности, я хочу затемнить все окно, кроме элемента управления, который я подчеркиваю.
Я попытался создать частично прозрачное черное наложение с помощью SetLayeredWindowAttributes
, но это не позволяет мне сделать подобласть полностью прозрачной. UpdateLayeredWindow
могу это сделать, но я не горю желанием создавать файл BMP / PNG для каждого элемента управления, который мне нужно выделить.
Могу ли я создать геометрию прозрачности динамически? Например, могу ли я нарисовать растровую прозрачность с нуля, а затем загрузить ее в UpdateLayeredWindow
?
Мне также необходимо быть совместимым с Windows 7 (несмотря на ее поддержку EOL).
Продолжение: Пытаюсь нарисовать прозрачные области GDI , но не работает:
void ApplicationDlg::Highlight(const CRectamp; rect)
{
CRect wndRect;
GetWindowRect(amp;wndRect);
Gdiplus::Rect wndRectPlus(wndRect.left, wndRect.top, wndRect.Width(), wndRect.Height());
Gdiplus::Region wndRegion(wndRectPlus);
Gdiplus::Rect controlRectPlus(rect.left, rect.top, rect.Width(), rect.Height());
Gdiplus::Region highlightRegion(controlRectPlus);
wndRegion.Exclude(amp;highlightRegion);
Gdiplus::SolidBrush transparentBrush(Gdiplus::Color(0, 0, 0, 0));
Gdiplus::SolidBrush darkenBrush(Gdiplus::Color(128, 0, 0, 0));
CDC* pDCScreen = m_WalkthroughDlg.GetDC();
HDC hDC = CreateCompatibleDC(pDCScreen->m_hDC);
HBITMAP hBmp = CreateCompatibleBitmap(hDC, wndRect.Width(), wndRect.Height());
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);
Gdiplus::Graphics graphics(hDC);
graphics.FillRegion(amp;darkenBrush, amp;wndRegion);
graphics.FillRegion(amp;transparentBrush, amp;highlightRegion);
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
SIZE sizeWnd = {wndRect.Width(), wndRect.Height()};
POINT ptSrc = {0,0};
m_WalkthroughDlg.UpdateLayeredWindow(pDCScreen, NULL, amp;sizeWnd, CDC::FromHandle(hDC), amp;ptSrc, NULL, amp;blend, ULW_ALPHA); // TODO cleanup FromHandle refs
m_WalkthroughDlg.BringWindowToTop();
SelectObject(hDC, hBmpOld);
DeleteObject(hBmp);
DeleteDC(hDC);
}
Ответ №1:
Вы можете динамически создавать маску с помощью CRgn
класса: https://learn.microsoft.com/en-us/cpp/mfc/reference/crgn-class?view=vs-2019
Это позволяет объединять области (если вам нужно выделить более одной области). Затем вы могли бы использовать FillRgn
функцию для обновления hdcSrc
постоянного тока, используемого в UpdateLayeredWindow
.
В качестве альтернативы, если ваши основные моменты прямоугольные, вы могли бы просто нарисовать прямоугольники на этом hdcSrc
.
Комментарии:
1. Пытаюсь использовать
Region
класс GDI , так как GDICRgn
не хватает прозрачности. Но, должно быть, что-то не так, окно наложения не отображается.2. Благодарен, если вы могли бы взглянуть на код, которым я обновил свой вопрос.
3. Что вы видите в этом последнем коде? Я не знаком с GDI , но мог бы взглянуть, если вы каким-то образом прикрепите свой проект сюда.
4. Окно полностью прозрачно на 100%, несмотря на проверку того, что прямоугольник управления значительно меньше прямоугольника окна. К сожалению, я не могу поделиться проектом.
5. У меня действительно нет времени создавать фиктивный проект скелета, чтобы играть с этим. Однако вы можете вернуться к своему первоначальному решению, но вместо одного темного наложения создайте четыре, чтобы окружить выделенный элемент управления: один сверху, один снизу и по два с каждой стороны.