Позвольте мне начать с Цель: Я собираюсь установить фон статического элемента управления в качестве диалогового окна, в то время как содержимое статического элемента управления не является фиксированной строкой и после оператора регистра переключателя изменяется. Другими словами, я собираюсь установить фон статического элемента управления с динамическим содержимым для диалогового окна со статическим изображением bimap.
Чтобы достичь этой цели, нужно обработать три сообщения, определенные ниже:
OnEraseBkgnd (), OnDestroy (), OnCtlColor ()
Чтобы показать тексты, после каждой инструкции Switch case я устанавливаю функцию SetWindowText:
::SetWindowText(GetDlgItem(IDC_STATIC_FORM)->m_hWnd, ArrayName);
Единственная проблема здесь была перекрытие. Все тексты из превью событий или дел остались на SetWindowText
, Чтобы решить эту проблему после каждого SetWindowText
InvalidateRect (Null) определен, и эта проблема также решена, но во время процедуры я получил диалоговое окно, которое всегда мигало и, если говорить технически, мерцало. Я думаю, что проблема только из-за Invalidate, который применяется ко всему диалогу, а не только к статическому контролю. OnCtlColor переопределяется для диалога, а не для элемента управления. Поскольку я просто хочу, чтобы элемент управления стал недействительным, я должен создать подкласс для элемента управления CStatic, переопределить только его OnCtlColor (не диалоговое окно) и вместо этого вызвать только его Invalidate.
Моя проблема:
Предполагая, что я объявил переменную для статического управления в основном коде и инициализировал ее в конструкторе, я определил класс с именем CSTATICCTRL с базовым классом CDialogEX, тогда обработчики сообщений были следующими:
Переменный член определяется как:
CSTATICCTRL m_STATIC_FORM;
а также
BOOL CSTATICCTRL::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmap* pOldbitmap = dcMemory.SelectObject(&Background);
CRect rcClient;
const CSize& sbitmap = bitmapSize;
pDC->BitBlt(0, 0, sbitmap.cx, sbitmap.cy, &dcMemory, 0, 0, SRCCOPY);
/*The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels
from the specified source device context into a destination device context.*/
dcMemory.SelectObject(pOldbitmap);
return 1;
//return CDialogEx::OnEraseBkgnd(pDC);
}
HBRUSH CSTATICCTRL::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
//HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd->GetDlgCtrlID() == IDC_STATIC_FORM)
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255, 255, 255));
Invalidate();
}
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
void CSTATICCTRL::OnDestroy() //free the resources created for the bitmap,
{
CDialog::OnDestroy();
Background.DeleteObject(); // Delete Background bitmap
BrushHol.DeleteObject();
// Delete Brush
}
Я оставил эти сообщения в основном коде тоже. Затем я попытался аннулировать статический контроль после каждого случая переключения следующим образом:
m_STATIC_FORM.Invalidate();
Кроме того, дескриптор PreSubclassWindow () добавлен в конец нового класса следующим образом.
void CSTATICCTRL::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
CDialogEx::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW); // make the button owner drawn
}
Ничего не случилось! Я не знаю, что случилось с моим кодом! Таким образом, содержимое статического элемента управления изменяется, но оно не прозрачно и перекрытия по-прежнему существуют.
ОБНОВИТЬ:
На самом деле, только сейчас я понял, что новый класс не влияет на статическое управление и диалоговое окно после комментирования некоторых строк !! Я думаю, что сначала я должен активировать CSTATICCTRL, затем я могу работать с его сообщениями дескриптора.
Для кода диалога используются эти три дескрипторных сообщения:
BOOL CMainDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
//************************************************************************************
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmap* pOldbitmap = dcMemory.SelectObject(&Background);
CRect rcClient;
GetClientRect(&rcClient);
const CSize& sbitmap = bitmapSize;
pDC->BitBlt(0, 0, sbitmap.cx, sbitmap.cy, &dcMemory, 0, 0, SRCCOPY);
dcMemory.SelectObject(pOldbitmap);
return TRUE;
//return CDialog::OnEraseBkgnd(pDC);
}void CMainDlg::OnDestroy() //free the resources created for the bitmap,
{
CDialog::OnDestroy();
// Delete Brush
}
HBRUSH CMainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
// TODO: Change any attributes of the DC here
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
Я не пробовал это, но я думаю, что это будет работать.
Override OnCtlColor
в вашем диалоге. Когда он обнаружит, что статический элемент управления рисуется, верните нулевую кисть. Это предотвращает стирание фона, что и вызывает мерцание.
Установить WS_EX_TRANSPARENT
стиль на вашем статическом контроле. Это приведет к тому, что часть диалогового окна под элементом управления будет перекрашена до того, как элемент управления будет нарисован, стирая старый текст.
Изменить: в соответствии с статья Рэймонда Чена WS_EX_TRANSPARENT
стиль не поможет в этом случае, потому что диалог не родственный элемент статического элемента управления, это родительский элемент. Вы можете перерисовать часть под вашим статическим контролем с помощью RedrawWindow
.
Тебе не нужен твой собственный класс, CStatic
будет хорошо работать с этими модификациями. если ты делать решить, что вам нужен собственный класс, вы не должны выводить его из CDialogEx
хотя, это должно быть зарезервировано для диалоговых окон.
pStatic->SetWindowText(str);
CRect rcChild;
pStatic->GetClientRect(&rcChild);
pStatic->MapWindowPoints(this, &rcChild);
RedrawWindow(rcChild, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
pStatic->InvalidateRect(NULL);