Ribbon background color cannot be set - winapi

To change the ribbon colors, from MSDN:
CComPtr<IPropertyStore> spPropertyStore;
// _spFramework is a pointer to the IUIFramework interface that is assigned
// when the Ribbon is initialized.
if (SUCCEEDED(_spFramework->QueryInterface(&spPropertyStore)))
{
PROPVARIANT propvarBackground;
PROPVARIANT propvarHighlight;
PROPVARIANT propvarText;
// UI_HSBCOLOR is a type defined in UIRibbon.h that is composed of
// three component values: hue, saturation and brightness, respectively.
UI_HSBCOLOR BackgroundColor = UI_HSB(0x14, 0x38, 0x54);
UI_HSBCOLOR HighlightColor = UI_HSB(0x00, 0x36, 0x87);
UI_HSBCOLOR TextColor = UI_HSB(0x2B, 0xD6, 0x00);
InitPropVariantFromUInt32(BackgroundColor, &propvarBackground);
InitPropVariantFromUInt32(HighlightColor, &propvarHighlight);
InitPropVariantFromUInt32(TextColor, &propvarText);
spPropertyStore->SetValue(UI_PKEY_GlobalBackgroundColor, propvarBackground);
spPropertyStore->SetValue(UI_PKEY_GlobalTextColor, propvarText);
spPropertyStore->Commit();
}
This does not work in Windows 10, background color is left unchanged. It works in Windows 7. Only the "File" is changed.
Any options?

Related

How do I make a combobox show a tab control like VS' when setting a color?

I mean this control:
When you click on this, instead of regular options, a tab control with the colors is displayed. How can I do this? is this a owner-draw combobox or something else? I'm aware on how draw text, rectangles, images, etc with a owner-draw combobox but I don't know how add controls over there. I have no code to show yet because I have no idea how do that. I've tried something like call CreateWindow() in WM_DRAWITEM using the values from DRAWITEMSTRUCT.rcItem but I can't make a control inside the groupbox's client area, the button gets behind the control.
Looks like you are looking for CBN_DROPDOWN.
Sent when the list box of a combo box is about to be made visible. The
parent window of the combo box receives this notification code through
the WM_COMMAND message.
Some code:
HWND hWndComboBox = CreateWindow(
WC_COMBOBOX,
TEXT(""),
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
10, 20, 70, 17,
hWnd, (HMENU)IDB_COMBOX, hInstance, NULL);
...
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDB_COMBOX:
{
switch (HIWORD(wParam))
{
case CBN_DROPDOWN:
{
CHOOSECOLOR cc; // common dialog box structure
static COLORREF acrCustClr[16]; // array of custom colors
static DWORD rgbCurrent; // initial color selection
// Initialize CHOOSECOLOR
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = hWnd;
cc.lpCustColors = (LPDWORD)acrCustClr;
cc.rgbResult = rgbCurrent;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
ChooseColor(&cc);
}
break;
...
Debug:

Can I make a property sheet without resource script?

I'd like to add controls to a property sheet without resource script, rather using pure code.
The reason for this I'd like to create a property sheet(mimicking C#'s property grid), calling C routines/WINAPI, from another language, binary-compatible to C; but I'd like to define everything with code, without need of a resource script. Is this possible or the way to go is write my own property-sheet-like, with underlying CreateWindow*() calls? (different approaches to do this are welcome, I'm new to WINAPI) which I suppose property sheet use behind the scenes
Found the solution! I found this post from Raymond Chen where he shows how do that.
the main code goes like this:
BOOL FakeMessageBox(HWND hwnd, LPCWSTR pszMessage, LPCWSTR pszTitle)
{
BOOL fSuccess = FALSE;
HDC hdc = GetDC(NULL);
if (hdc) {
NONCLIENTMETRICSW ncm = { sizeof(ncm) };
if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) {
DialogTemplate tmp;
// Write out the extended dialog template header
tmp.Write<WORD>(1); // dialog version
tmp.Write<WORD>(0xFFFF); // extended dialog template
tmp.Write<DWORD>(0); // help ID
tmp.Write<DWORD>(0); // extended style
tmp.Write<DWORD>(WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_MODALFRAME);
tmp.Write<WORD>(2); // number of controls
tmp.Write<WORD>(32); // X
tmp.Write<WORD>(32); // Y
tmp.Write<WORD>(200); // width
tmp.Write<WORD>(80); // height
tmp.WriteString(L""); // no menu
tmp.WriteString(L""); // default dialog class
tmp.WriteString(pszTitle); // title
// Next comes the font description.
// See text for discussion of fancy formula.
if (ncm.lfMessageFont.lfHeight < 0) {
ncm.lfMessageFont.lfHeight = -MulDiv(ncm.lfMessageFont.lfHeight,
72, GetDeviceCaps(hdc, LOGPIXELSY));
}
tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfHeight); // point
tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfWeight); // weight
tmp.Write<BYTE>(ncm.lfMessageFont.lfItalic); // Italic
tmp.Write<BYTE>(ncm.lfMessageFont.lfCharSet); // CharSet
tmp.WriteString(ncm.lfMessageFont.lfFaceName);
// Then come the two controls. First is the static text.
tmp.AlignToDword();
tmp.Write<DWORD>(0); // help id
tmp.Write<DWORD>(0); // window extended style
tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE); // style
tmp.Write<WORD>(7); // x
tmp.Write<WORD>(7); // y
tmp.Write<WORD>(200-14); // width
tmp.Write<WORD>(80-7-14-7); // height
tmp.Write<DWORD>(-1); // control ID
tmp.Write<DWORD>(0x0082FFFF); // static
tmp.WriteString(pszMessage); // text
tmp.Write<WORD>(0); // no extra data
// Second control is the OK button.
tmp.AlignToDword();
tmp.Write<DWORD>(0); // help id
tmp.Write<DWORD>(0); // window extended style
tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE |
WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style
tmp.Write<WORD>(75); // x
tmp.Write<WORD>(80-7-14); // y
tmp.Write<WORD>(50); // width
tmp.Write<WORD>(14); // height
tmp.Write<DWORD>(IDCANCEL); // control ID
tmp.Write<DWORD>(0x0080FFFF); // static
tmp.WriteString(L"OK"); // text
tmp.Write<WORD>(0); // no extra data
// Template is ready - go display it.
fSuccess = DialogBoxIndirect(g_hinst, tmp.Template(),
hwnd, DlgProc) >= 0;
}
ReleaseDC(NULL, hdc); // fixed 11 May
}
return fSuccess;
}

Setting a window's background to an unusual pattern before drawing into it

I have a window (CWnd object), into which I am drawing a bitmap image.
Before doing so, I would like to set the window's background to a specific pattern.
The pattern may change from time to time.
If I understand correctly, then I need to override the window's OnCtlColor function, and return a brush compatible with my desired pattern (recalculated according to internal data-structure).
Am I on the right track?
The pattern is rather irregular. It consists of "zebra stripes", all of which are of the same width, but (may be) of different heights. Here is an illustrated example:
Is it even possible to create a brush with such pattern?
If yes, then which of the following functions would be the most appropriate:
CBrush::CreateBrushIndirect
CBrush::CreateDIBPatternBrush
CBrush::CreateHatchBrush
CBrush::CreatePatternBrush
Thank you.
I wouldn't even bother with brushes. This example draws a bunch of stripes using FillSolidRect and stripe heights in screen height percentages. Should be easy to adjust if you're using absolutes.
BOOL CChildView::OnEraseBkgnd(CDC* pDC)
{
CRect clientRect;
GetClientRect(clientRect);
const auto savedDC = pDC->SaveDC();
// Make the co-ordinates system behave like percentages
{
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(100, 100);
pDC->SetViewportExt(clientRect.right, clientRect.bottom);
}
// pair requires #include <utility>
std::pair<int, COLORREF> stripeData[] =
{
{ 8, RGB(220,220,220) }, // 8% of window height, light grey
{ 17, RGB(165,165,165) }, // 17% of window height, dark grey
{ 12, RGB(220,220,220) }, // etc. These should total 100%
{ 7, RGB(165,165,165) },
{ 23, RGB(220,220,220) },
{ 33, RGB(165,165,165) }
};
// NOTE: FillSolidRect changes the background color, so restore it at the
// end of the function. RestoreDC will handle this; otherwise save the
// GetBkColor return value and restore it by calling SetBkColor
//auto oldBkColor = pDC->GetBkColor();
// Draw the stripes
CRect stripeRect{0,0,100,0};
for (auto const& data : stripeData)
{
stripeRect.bottom = stripeRect.top + data.first;
pDC->FillSolidRect(stripeRect, data.second);
stripeRect.OffsetRect(0, data.first);
}
//pDC->SetBkColor(oldBkColor);
pDC->RestoreDC(savedDC);
return TRUE;
}

Mfc Font binding and Rich Edit Control RICHEDIT50W does not display Unicode Properly

Latest update:
Well, I found a culprit of some sort. I changed the control to RichEdit20W from the 50W and it displays the Hangul (Korean) now. I did not have to change any other code except for the init, added AfxInitRichEdit2(), and commented out the LoadLibrary(L"MsftEdit.dll"). The AfxInitRichEdit5() is not available for VS2010. All things being equal and Rich Edit 4.1 has been available since VS2005, it should have worked. I can't upgrade to VS2015 right now so I'm stuck. I'm going to offer a bounty though for anybody who can make the Hangul work with 50W and VS2010.
I have a dilemma that I can't seem to solve.
I have an mfc Unicode app that uses CEdit and CRicheditCtrl.
The Rich Edit is 50W loaded from MsftEdit.dll and verified with Spy++
that the class name is RICHEDIT50W.
My problem:
I'm using the same Font Courier New for both the CEdit and CRichEditCtrl.
As a test, I used some of the Hangul symbols to see the output for both
controls.
CEdit outputs ᄀᄁᄂᄃᄄᄅᄆᄇᄈ
while the
CRichEditCtrl outputs a box for each character, like there is no glyph for it.
If they are using the same font, shouldn't I see the same output characters?
I think that font-binding is not a problem, both have the same default font.
Can anybody solve this riddle ?
Thanks in advance!
Note that this happens with some other character sets as well, not just Hangul
Update
I looked at the VS2010 WordPad example, it uses CRichEditView but it
provides wrappers to access the embedded CRichEditCtrl.
I thought I could glean some info but I can't see how they are doing the
Rich Edit control calls.
This is how I am generating the font's for both controls.
But, I'm showing specifically the Rich Edit part.
The doc's say that Font binding should handle switching from the default
font to the font at the current insertion point.
I am doing insertion mostly at the end using
ctrl.SetSel(-1,-1);
ctrl.ReplaceSel( str );
And, according to the doc's, this should change to the correct font as needed,
if other than the default font.
In the WordPad sample, if I paste in the Hangul text, the font switches to
Gulim.
Here is my code:
LOGFONT lf;
int pitch = 10;
memset(&lf, 0, sizeof(LOGFONT));
HDC hdc = ::GetDC(NULL);
lf.lfHeight = -MulDiv( pitch, GetDeviceCaps(hdc, LOGPIXELSY), 72);
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lstrcpy(lf.lfFaceName, _T("Courier New") );
lf.lfWeight = FW_NORMAL;
lf.lfCharSet = ANSI_CHARSET; // English, but use DEFAULT_CHARSET if not
lf.lfQuality = DEFAULT_QUALITY;
if ( !m_Font.CreateFontIndirect(&lf) )
{ // Ours didn't work, create a system default fixed font
// ( Ignore, example for post only. Never gets called though )
//memset(&lf, 0, sizeof(LOGFONT));
//::GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
//m_Font.CreateFontIndirect(&lf);
}
// Save the generated Font LOGFONT
m_lf = lf;
// Set the default Font CHARFORMAT2
memset( &m_cfDefaultFont, 0, sizeof(m_cfDefaultFont) );
m_cfDefaultFont.cbSize = sizeof(m_cfDefaultFont);
m_cfDefaultFont.dwMask = CFM_CHARSET | CFM_FACE | CFM_WEIGHT ;
m_cfDefaultFont.bCharSet = m_lf.lfCharSet;
lstrcpy( m_cfDefaultFont.szFaceName, m_lf.lfFaceName );
m_cfDefaultFont.wWeight = m_lf.lfWeight;
// Finally set the font in the controls
m_RichEdit.SetFont( &m_Font );
// Same effect as m_RichEdit.SetFont()
//m_RichEdit.SendMessage(EM_SETCHARFORMAT, SCF_ALL, &m_cfDefaultFont);
// This displays nothing but 'box' glyphs
m_RichEdit.SetWindowTextW(_T("ᄃᄄᄅᄆᄇᄈᄉᄊᄋᄌᄍᄎ"));
Update 2
This is how I initialize the Rich Edit in the app.
And shows the usage of 50W in a dialog control.
-- winapp.cpp
BOOL CMyApp::InitInstance()
{
// ...... //
CString strRichEdit = _T("Msftedit.dll");
m_hMsfteditDll = AfxLoadLibrary( strRichEdit );
if ( m_hMsfteditDll == NULL )
{
CString str;
str.Format(_T("Error: Cannot find Rich Edit component %s"), strRichEdit );
AfxMessageBox(str);
return FALSE;
}
return TRUE;
}
int CRegexFormatApp::ExitInstance()
{
if ( m_hMsfteditDll != NULL )
AfxFreeLibrary( m_hMsfteditDll );
return CWinAppEx::ExitInstance();
}
// =========================
-- .rc
CONTROL "",IDC_RICH_EDIT,"RICHEDIT50W",WS_VSCROLL | WS_HSCROLL,40,15,148,28
-- Dlg.h
CRichEditCtrl m_RichEdit;
-- Dlg.cpp
void Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_RICH_EDIT, m_RichEdit); // Use .rc setting to Create/Attach
}
BOOL Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
CreateAndSetRichFont(); // Code shown above
m_RichEdit.SetWindowTextW( ... );
}
This code should work in a Unicode project:
BOOL CMyApp::InitInstance()
{
CWinApp::InitInstance();
LoadLibrary(L"MsftEdit.dll");
...
}
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
static CRichEditCtrl redit;
CWnd *wnd = &redit;
wnd->Create(MSFTEDIT_CLASS, L"ᄃᄄᄅᄆᄇᄈᄉᄊᄋᄌᄍᄎ",
WS_CHILD | WS_VISIBLE, CRect(0,0,300,300), this, 1001, 0);
...
//redit is not to be mixed up with controls created in dialog editor.
}
Edit ----------------
NONCLIENTMETRICS info = { sizeof(info) };
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
LOGFONT logfont = info.lfMessageFont;
//CClientDC has automatic cleanup, use it instead of GetDC
CClientDC dc(this);
logfont.lfHeight = -MulDiv(abs(logfont.lfHeight), dc.GetDeviceCaps(LOGPIXELSY), 76);
CFont font;
font.CreateFontIndirect(&logfont);
m_RichEdit.SetFont(&font);
m_RichEdit.SetWindowText(L"ᄃᄄᄅᄆᄇᄈᄉᄊᄋᄌᄍᄎ");
m_RichEdit.SetSel(1, 1);
CString test = L"(Test, ελληνικά)";
//Test to make sure we can see Unicode text
AfxMessageBox(test);
m_RichEdit.ReplaceSel(test);
//optional:
//get default CHARFORMAT
CHARFORMAT2 charFormat;
//m_RichEdit.GetSelectionCharFormat(charFormat);
m_RichEdit.GetDefaultCharFormat(charFormat);

CListCtrl set font style to bold

I want to change font of any cell of CListCtrl control to bold. Can any one tell how to do it for CList Ctrl.
I have already done this for a CTreeCtrl, like this
pTC->SetItemState(hItemCur, TVIS_BOLD, TVIS_BOLD);
do we have something similar for CListCtrl?
Thanks in advance.
If you can use CMFCListCtrl (VS2008 SP1 and up), you can derive a class from it and override OnGetCellFont. From there you return your bold font (you can create your own or return AFX_GLOBAL_DATA::fontBold):
HFONT CMyListCtrl::OnGetCellFont( int nRow, int nColumn, DWORD dwData /*= 0*/ )
{
if (UseBoldFont(/* params */))
{
return GetGlobalData()->fontBold;
}
return NULL;
}
If you have to stick to plain old CListCtrl, the easiest way would be to use Custom Draw, where you can tweak the drawing process to your own needs. Don't confuse it with Owner Draw, where you have to do all the drawing yourself.
Here's an article explaining the basics of using Custom Draw with CListCtrl.
Add
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdraw)
to your message map.
Now you can simply modify items as you wish in this function. In here you can change the align, font, background-color, text-color, [...], and you can set items to bold -> example. The best way IMO, is to either store a pointer to a struct, class or simply a flag in the LPARAM of the item(s) in the control. This function works for both CListCtrl and CTreeCtrl.
Here is an example with flags:
enum ColorFlags
{
F_COLOR_BLACK = 0x1,
F_COLOR_WHITE = 0x2
//and more...
};
enum CustomColors
{
COLOR_BLACK = RGB(0, 0, 0),
COLOR_WHITE = RGB(255, 255, 255)
};
afx_msg
void CMyListCtrl::OnCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVCUSTOMDRAW *pDraw = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
switch (pDraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW; //Do not forget this...
break;
case CDDS_ITEMPREPAINT:
{
switch (pDraw->nmcd.lItemlParam) //Extract color from flags
{
case F_COLOR_BLACK:
{
pDraw->clrText = COLOR_BLACK;
} break;
case F_COLOR_WHITE:
{
pDraw->clrText = COLOR_WHITE;
} break;
default:
break;
} //switch
} break;
} //switch
}

Resources