2013-02-23 2 views
1

Я использую Visual Studio 2010 для создания приложения native/win32/MFC C++. У меня есть диалог, в котором я хочу, чтобы пользователь мог ввести дату. Для этого я использовал CDateTimeCtrl, который является оберткой общих элементов управления Win32.собственный календарный контроль C++/Win32/MFC с настраиваемым размером шрифта

Это хорошо, так как пользователь может щелкнуть стрелку, и она опустится на месяц, позволяя им в интерактивном режиме выбрать дату.

Проблема, с которой я столкнулся, заключается в том, что вы не можете контролировать размер шрифта, используемый в представлении месяца. Он игнорирует WM_SETFONT и, хотя в документации по управлению упоминаются вызовы, которые скажут ему использовать пользовательский шрифт (см. CDateTimeCtrl :: SetMonthCalFont()), они игнорируются.

Я обнаружил, наконец, через службу технической поддержки MS, что он работает в v5 общих элементов управления, но в v6 они изменили его, чтобы игнорировать это и просто использовать текущую информацию о визуальном стиле, установленную в Windows. Согласно MS нет способа получить собственный шрифт, элемент управления в v6 будет использовать только текущий визуальный стиль Windows. Единственным способом было бы принудительное использование элементов управления v5, таким образом, сбросив все пользовательский интерфейс вашего приложения обратно в элементы управления v5 или запутавшись с пользовательскими контекстами активации (звучит беспорядочно).

Итак, я ищу альтернативный контроль. Может ли кто-нибудь рекомендовать собственный/C++/MFC-элемент управления, который предоставляет что-то подобное, но который позволяет мне настроить общий размер шрифта? Я использую шрифт большего, чем обычно, в диалоговом окне и всех других элементах управления, и он отлично выглядит, за исключением этого элемента управления календарем. Пока что мой первоначальный поиск не принес ничего, что похоже на решение.

ответ

2

Посмотрите на функцию SetWindowTheme. С его помощью вы можете отключить тему XP только для некоторых элементов управления в своем приложении, сохраняя другие.

Согласно MSDN:

Когда pszSubAppName и pszSubIdList являются NULL, менеджер тему удаляет ранее примененные ассоциации. Вы можете запретить применение визуальных стилей к указанному окну, указав пустую строку (L ""), которая не соответствует элементам раздела.

+0

приятно! Похоже, это может сделать именно то, что мне нужно. Я проверю и посмотрю, что будет завтра. – Nerdtron

+0

Интересно, что он говорит «указывая пустую строку», но при этом предоставляет непустую строку в качестве примера. Их пример L "", который содержит одно пространство. Кажется, что не работает, но я все еще пытаюсь выяснить, какую комбинацию NULL и L "или L" использовать и для какого из двух аргументов: – Nerdtron

+0

Вот пример использования SetWindowTheme для удаления визуальных стилей, и кажется, что они пропускают пустую строку для обоих аргументов (http://www.logix-controls.com/SwiftForth/XP-Themes/Using%20Windows%20XP%20Visual%20Styles.txt). Конечно, здесь, как и в документах MSDN, «пустая строка» выглядит как непустая строка с одним пробелом, поэтому я предполагаю, что это то, что предназначено. Кажется, что это не работает. – Nerdtron

1

Ответ от cha выше является правильным решением. Чтобы получить контроль над вызовом SetMonthCalFont, вам необходимо отключить визуальную тему. Однако есть некоторые трюки.

1) вы не можете просто вызвать SetWindowTheme на объекте CDateTimeCtrl, поскольку вызов применяется только к этому непосредственному окну, а не к дочерним окнам. Выпадающий месяц - это дочернее окно и, таким образом, не затрагивается. Поэтому вместо этого вы должны обрабатывать уведомление DTN_DROPDOWN для элемента управления и получать контрольный элемент дочернего месяца и удалять из него визуальную тему.

2) Размер/позиция дочернего элемента месяца определяется до отправки уведомления DTN_DROPDOWN. Так что, даже если вы делаете № 1 выше, он не будет правильно подбираться. Итак, вы должны обновить размер.

3) Очевидно, что намерение состоит в том, чтобы передать пустую строку, а не строку с 1 пробелом, несмотря на то, что, по-видимому, указывают документы MSDN.

4) В приведенном ниже коде не учитывается случай, когда раскрывающееся управление календарем близко к краю экрана. Возможно, что, если это произойдет, код нужно будет изменить для учета его и сдвинуть его положение, чтобы оно все еще было видимым.

Данная информация была предоставлена ​​Дэйвом Андерсоном в Microsoft Support, а также приведенным ниже кодом, который разрешил проблему и правильно отобразил элемент управления с помощью специального шрифта.

Итак, я вызываю SetMonthCalFont() в объекте CDateTimeCtrl в диалоге InitInstance(), а затем также обрабатываю уведомление DTN_DROPDOWN, используя приведенный ниже код.

Обратите внимание, что Дэйв предупредил, что «этот подход зависит от деталей реализации элемента управления датами и времени, которые могут быть изменены в будущем и могут привести к поломке кода ниже».

void DSomeDialog::OnDtnDropdownMyDateTimeCtrl(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
HWND hWndDateTime = (HWND)pNMHDR->hwndFrom; 
HWND hWndMonthCal = DateTime_GetMonthCal(hWndDateTime); 
HWND hWndDropDown = ::GetParent(hWndMonthCal); 
DWORD dwWidth; 
WINDOWINFO wi; 

if (hWndMonthCal && hWndDropDown) 
{ 
    RECT rcIdeal; 

    // 
    // Remove the window theme from the month calendar 
    // control 
    SetWindowTheme(hWndMonthCal, L"", L""); 

    // 
    // Get the ideal size of the month calendar control 
    ZeroMemory(&rcIdeal, sizeof(rcIdeal)); 
    MonthCal_GetMinReqRect(hWndMonthCal, &rcIdeal); 
    dwWidth = MonthCal_GetMaxTodayWidth(hWndMonthCal); 
    if (dwWidth > (DWORD)rcIdeal.right) 
    { 
     rcIdeal.right = dwWidth; 
    } 

    // 
    // Add some padding 
    InflateRect(&rcIdeal, 3, 3); 

    // 
    // Determine the new size of the drop down window such 
    // that the client area of the window is large enough 
    // to display the month calendar control 
    ZeroMemory(&wi, sizeof(wi)); 
    wi.cbSize = sizeof(WINDOWINFO); 
    ::GetWindowInfo(hWndDropDown, &wi); 
    AdjustWindowRectEx(&rcIdeal, wi.dwStyle, FALSE, wi.dwExStyle); 

    // 
    // Update the size of the drop down window 
    ::SetWindowPos(hWndDropDown, 
     NULL, 
     0, 
     0, 
     rcIdeal.right - rcIdeal.left, 
     rcIdeal.bottom - rcIdeal.top, 
     SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER); 
} 

*pResult = 0; 
} 
Смежные вопросы