c++

2017年05月27日

vs2017でのboost ビルド時エラー

vs2017 でboost1.64.0 をビルドしようとしたときに所々でエラーが出たのでその時のメモです。

環境

ツールまわり

  • visual studio 2017
  • Windows Kits 10.0.15063.0

実行環境

x86 Native Tools Command Prompt for VS 2017 を管理者権限にて実行

bootstrap.bat から呼び出される %boost_root%/tools/build/src/engine/build.bat には次のように書いてありました。

If you have Visual Studio 2017 installed you will need to build from
the Visual Studio Command Prompt for VS 2017 as we where unable to
detect your toolset installtion.

エラー

ことの始まりはbootstrap.bat を動かしたときの次のエラーでした。

execnt.c(57): fatal error C1083: include ファイルを開けません。'tlhelp32.h':No such file or directory

ということで、b2.exe とかbjam.exe が作られませんでした。

tlhelp32.h

tlhelp32.h 自体のことについては置いておいて、見つからないと言われるので適当なプロジェクトでインクルードしてみると、

C:\Program Files (x86)\Windows Kits\8.1\Include\um\TlHelp32.h

にあるとのこと。あるじゃん…
それはそうと、Prompt 上のインクルードパスを調べたところ、Windows Kits は8.1 ではなく10系列が設定されていました。

C:\Program Files (x86)\Windows Kits\10\include\10.0.15063.0\...

上記ディレクトリ以下でtlhelp32.h があるか確認したところ、ありませんでした。それじゃあ見つからないと言われるのも仕方がないですね。

visual studio 2017 を最初に入れた時にWindows Kits は10.0.14393.0 が入っていたのでそちらを確認するとファイルはあったのでどうにか14393を使うようにしたところb2.exe とかbjam.exe が作られました。

エラーは続くよ

そのあとboost をビルドしようとすると、winsock2 のインクルードでやっぱりWindows Kits は10.0.15063.0 のディレクトリを参照しようとしました...

オチ

さいごに、初心に戻ってインストーラをまた立ち上げてみたところデスクトップC++x86およびx64用 Windows 10 SDK (10.0.15063.0) がチェックついてませんでした…
チェックつけてやり直したらうまくいったので、もし同じ困り方をしたらこのコンポーネントがちゃんと入っているかチェックしてみてください。

全部ちゃんとインストールしてたと思ったのに哀しかったです...



rabbitcats at 12:01|PermalinkComments(0)

2014年11月26日

動的にアイコンを変えられるツールバー

C++ でMFC を利用してデスクトップアプリケーションの開発をしていた時の覚書です。
画面を切り替えて使うアプリケーションなどでは、画面ごとに似たような機能を持ったツールバーを用意することがあると思います。
その場合に一つのツールバーで見た目と機能を切り替えると便利かと思ったので、試してみました。

下準備

CMFCToolBar を継承した新しいToolBar クラスを作成し、下記の関数をオーバーライドします。

BOOL CMyToolBar::LoadToolBar(UINT uiResID, UINT uiColdResID, UINT uiMenuResID, BOOL bLocked,
        UINT uiDisabledResID, UINT uiMenuDisabledResID,  UINT uiHotResID)
{
    m_uiOriginalResID = 0;
    return CMFCToolBar::LoadToolBar(uiResID, uiColdResID, uiMenuResID, bLocked, uiDisabledResID, uiMenuDisabledResID, uiHotResID);
}

BOOL CMyToolBar::LoadToolBarEx(UINT uiToolbarResID, CMFCToolBarInfo& params, BOOL bLocked)
{
    m_uiOriginalResID = 0;
    return CMFCToolBar::LoadToolBarEx(uiToolbarResID,params,bLocked);
}

実際にはLoadToolBar は内部でLoadToolBarEx を呼び出しているので、LoadToolBarEx だけオーバーライドすればできると思います。
動的にアイコンを変えたい場合にはm_uiOriginalResID の値を0 にしてあげる必要があります。
これはCMFCToolBar::LoadToolBarEx 内でビットマップをロードするLoadBitmapEx と同じ条件式のところで、m_uiOriginalResID の値を見ているからです。

if (m_uiOriginalResID != 0 || LoadBitmapEx(params, bLocked))

afxtoolbar.cpp のLoadToolBarEx 内でこのようにコードが書かれています(VisualStudio12.0で確認)。 m_uiOriginalResID が0 以外の場合ではLoadBitmapEx が呼び出されないため、変更したいツールバーのビットマップが読み込まれないことになってしまいます。

使い方

使い方は簡単で、いつも通りツールバーを作成します。

m_pMyToolBar->CreateEx(
    this,
    TBSTYLE_FLAT,
    WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC,
    CRect(0, 0, 0, 0),
    MYTOOLBAR1_ID
    );
m_pMyToolBar->LoadToolBar(IDR_MYTOOLBAR1, 0, 0, TRUE);
m_pMyToolBar->SetWindowText(_T("MyToolbar1"));
m_pMyToolBar->SetControlBarStyle(m_pMyToolBar->GetControlBarStyle() & ~AFX_CBRS_CLOSE);

this->DockPane(m_pWndToolBar.get());

そのあとに変更したいタイミング(たとえばツールバーのアイコンをクリックしたタイミングなど)で下記のコードを呼び出します。

m_pMyToolBar->CleanUpLockedImages();
m_pMyToolBar->LoadToolBar(IDR_MYTOOLBAR2, 0, 0, TRUE);
m_pMyToolBar->AdjustLayout();
m_pMyToolBar->AdjustSizeImmediate();

これで無事にツールバーを変更することができます。

おまけ

実は上に書いたコードには落とし穴がありました。
ツールバーを作成した後に
m_pMyToolBar->SetControlBarStyle(m_pMyToolBar->GetControlBarStyle() & ~AFX_CBRS_CLOSE);
でツールバーの閉じるボタンを無効に設定しているのですが、実際には閉じるボタンは表示されてしまいます。

CMFCToolBar::CanBeClosed

CanBeClosed で閉じることができるかどうかを判断できるのですが、CMFCToolBar は常にTRUE を返すようです。
ちょっと意味が分からないですね。
そこで、とりあえず下記のようにオーバーライドすることで設定した値で判断するように変更できます。

BOOL CMyToolBar::CanBeClosed() const
{
    return CBasePane::CanBeClosed();
}

これで解決できるのですが、良いのかどうか・・・



rabbitcats at 00:50|PermalinkComments(0)TrackBack(0)