お世話になります。
Windows7, VisualStudio 2010 Pro
現在、オーナードロー形式のポップアップメニューを作成しているのですが、
セパレータの描画でちょっと困っています。
Windows7の標準テーマではセパレータの色はかなり薄い灰色+白色の2重線に見えます。
一方、Windowsクラシックなどのテーマだと、濃いグレー+白色の2重線に見えます。
他のデスクトップテーマなどを選択した場合にもそれぞれの配色が
システムによって決められています。
これらのテーマに合ったセパレータの色をGetSysColor()で取得したいと思っているので
すが、
どうもうまくいきません。
いろいろと実験した結果、以下のパターンが一番無難ではあるようです。
COLORREF rgbSep1 = GetSysColor(COLOR_BTNSHADOW); // 灰色
COLORREF rgbSep2 = GetSysColor(COLOR_BTNHIGHLIGHT); // 白色
ただし、この場合はWindows 7の標準テーマの場合、薄い灰色がシステム標準よりも濃い
色になってしまいます。
COLOR_3DLIGHTにすると薄い灰色が出ますが、Windowsクラシックテーマにすると、
メニューの背景色と同じになってしまって線が見えません。
どのような定数(COLOR_????)を取れば、テーマに合ったセパレータの色が取得できるの
でしょうか?
よろしくお願い致します。
正直あっているか全く自信はないです。
テーマにそった描画はXP以降のAPIでできます。
(それより前をサポートする場合はLoadLibraryで動的にUxTheme.dllをロードしてください)
いろいろ試したところ
OpenThemeData関数でMENUのテーマハンドルを取得後、
DrawThemeBackgroundでMENU_POPUPSEPARATORを指定して描画するとそれっぽくなったり。
いろいろ調べてみてください。
一応試したコード
(VS2005,Win7,MFCダイアログベース)
hogeDlg.cpp
#pragma comment(lib, UxTheme.lib)
void ChogeDlg::OnPaint()
{
if (IsIconic())
{
// 略
}
else
{
CPaintDC dc(this);
CRect rc(10, 10, 110, 10);
HTHEME hTheme = ::OpenThemeData(this->GetSafeHwnd(), LMenu);
if (hTheme != NULL)
{
rc.top -= 3; rc.bottom += 3;
// MENU_POPUPSEPARATOR : 15
::DrawThemeBackground(hTheme, dc.GetSafeHdc(), 15, 0, rc, rc);
::CloseThemeData(hTheme);
}
else {
dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP);
}
CDialog::OnPaint();
}
}
> どのような定数(COLOR_????)を取れば、テーマに合ったセパレータの色が取得で
> きるのでしょうか?
これって各WINDOWSのバージョン等で決めてると思います。
http://wisdom.sakura.ne.jp/system/winapi/win32/win60.html
レジストリーで決めているみたいです。
蒼の洞窟 様
テーマのコンポーネントを描画するAPIがあったんですね。
知りませんでした。これでいけそうな感じです。
貴重なアドバイスありがとうございました。
>>rc.top -= 3; rc.bottom += 3;
ここ適当にやったけどGetThemePartSizeを使ったほうがよさげかも。
rc = CRect(10, 10, 110, 10);
HTHEME hTheme = ::OpenThemeData(m_hWnd, LMenu);
if (hTheme != NULL)
{
CSize s;
// MENU_POPUPSEPARATOR : 15
::GetThemePartSize(hTheme, NULL, 15, 0, NULL, TS_TRUE, &s);
//MARGINS m;
//::GetThemeMargins(hTheme, NULL, 15, 0, TMT_SIZINGMARGINS, NULL, &m);
rc.top -= s.cy / 2;
rc.bottom = rc.top + s.cy;
//rc.right += s.cx;
::DrawThemeBackground(hTheme, dc.GetSafeHdc(), 15, 0, rc, NULL);
::CloseThemeData(hTheme);
}
else {
dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP);
}