none
MFCアプリケーションでのBeginPanningFeedback RRS feed

  • 質問

  • Visual Studio 2015にてMFCアプリケーションを作成しています。
    アプリケーション内でBeginPanningFeedback、UpdatePanningFeedback、EndPannigFeedback関数を使用しようとしているのですが、これら3つの関数がリンクエラーとなりリンクできません。

    error LNK2019: 未解決の外部シンボル _BeginPanningFeedback@4 が関数...

    error LNK2019: 未解決の外部シンボル _UpdatePanningFeedback@16 が関数...

    error LNK2019: 未解決の外部シンボル _EndPanningFeedback@8 が関数...

    UxTheme.hをインクルードしていて、プロジェクトのプロパティのリンク→入力→追加の依存ファイルにUxTheme.libを指定しています。

    同じことをWindowsアプリケーション(MFCを使用せず)で行うと、正しくリンクできるようです。

    この症状の解決方法はありますでしょうか?



    • 編集済み syaki 2016年4月1日 9:05
    2016年4月1日 8:15

回答

  • 原因は、
    BeginPanningFeedback、UpdatePanningFeedback、EndPannigFeedback 関数は C++ リンケージで定義されているのですが、ヘッダーファイル「uxtheme.h」が C リンケージで読み込まれているからです。この場合、dwmapi.lib をリンクしても、前述の関数シンボルが見つからなくなります。

    私の環境ではインクルードの順序は下記のようになっていました。

    "[プロジェクトフォルダ]\stdafx.h"
    "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxwin.h"
    "C:\Program Files (x86)\Windows Kits\8.1\Include\um\dwmapi.h"
    "C:\Program Files (x86)\Windows Kits\8.1\Include\um\Uxtheme.h"

    上記の dwmapi.h の中で

    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    <中略>
    
    #include <uxtheme.h>
    
    <中略>
    
    #ifdef __cplusplus
    }
    #endif

    というような感じで include されていました。

    1つの解決方法は、
    MFCのヘッダー中で Uxtheme.h をインクルードさせないように _UXTHEME_H_ を定義し、その後自分で関数の宣言を行います。以下のように stdafx.h の中の

    #include <afxwin.h>         // MFC のコアおよび標準コンポーネント

    の部分を下記のように置き換えます

    #define _UXTHEME_H_
    
    typedef struct _MARGINS
    {
    int cxLeftWidth;      // width of left border that retains its size
    int cxRightWidth;     // width of right border that retains its size
    int cyTopHeight;      // height of top border that retains its size
    int cyBottomHeight;   // height of bottom border that retains its size
    } MARGINS, *PMARGINS;
    
    #include <afxwin.h>         // MFC のコアおよび標準コンポーネント
    
    BOOL WINAPI
    BeginPanningFeedback(
    __in HWND hwnd);
    
    BOOL WINAPI
    UpdatePanningFeedback(
    __in HWND hwnd,
    __in LONG lTotalOverpanOffsetX,
    __in LONG lTotalOverpanOffsetY,
    __in BOOL fInInertia);
    
    BOOL WINAPI
    EndPanningFeedback(
    __in HWND hwnd,
    __in BOOL fAnimateBack);
    
    // Uxtheme.h はインクルードせず Uxtheme の使いたいAPIは自分で宣言して下さい。

    ※構造体 _MARGINS を定義しているのは afxwin.h の中で使われているからです。

    ちなみに、VS2008 を確認してみましたが、afxwin.h の中でリンケージ指定なしで Uxtheme.h がインクルードされていました。リンクエラーにならなかったのはそのためですね。なぜ今のような設定になっているか知る由はありませんが、不具合とも取れますね。
    Uxtheme の中の3つ関数 BeginPanningFeedback、UpdatePanningFeedback、EndPannigFeedback 以外は C リンケージで定義されているので他の Uxtheme 関数のリンクは既定でも普通にリンクできました。


    以上参考になりましたら幸いです。





    • 編集済み kenjinoteMVP 2016年4月3日 3:22
    • 回答としてマーク syaki 2016年4月4日 0:44
    2016年4月2日 10:57

すべての返信

  • すみません。解決方法というよりは、回避方法ですが、

    動的リンクで、関数をロードしてみてはいかがでしょうか?

    ヘッダー部

    typedef BOOL(WINAPI * BeginPanningFeedbackPtr)(HWND hWnd);
    typedef BOOL(WINAPI * UpdatePanningFeedbackPtr)(HWND hWnd, LONG offsetX, LONG offsetY, BOOL fInInertia);
    typedef BOOL(WINAPI * EndPanningFeedbackPtr)(HWND hWnd, BOOL fAnimateBack);
    BeginPanningFeedbackPtr beginPanningFeedback = 0;
    UpdatePanningFeedbackPtr updatePanningFeedback = 0;
    EndPanningFeedbackPtr endPanningFeedback = 0;
    

    クラスの初期化部

    HMODULE hTheme = ::LoadLibrary(TEXT("uxtheme.dll"));
    if (hTheme)
    {
    	beginPanningFeedback = (BeginPanningFeedbackPtr)GetProcAddress(hTheme, "BeginPanningFeedback");
    	updatePanningFeedback = (UpdatePanningFeedbackPtr)GetProcAddress(hTheme, "UpdatePanningFeedback");
    	endPanningFeedback = (EndPanningFeedbackPtr)GetProcAddress(hTheme, "EndPanningFeedback");
    }
    上記の関数が正しくロードできた場合(非ゼロの場合)は
    BeginPanningFeedback、UpdatePanningFeedback、EndPannigFeedback関数
    を使う代わりに、beginPanningFeedback、updatePanningFeedback、endPanningFeedback関数を使用します。

    2016年4月1日 10:13
  • ソースコードのどこかに

    #pragma comment(lib, "UxTheme.lib")

    と記述して改善されるようであれば、プロジェクトのプロパティ設定が意図通り行われていないということになります。個人的にはプロジェクトに設定を行うよりもソースコード中に記述することをお勧めします。

    2016年4月1日 10:48
  • ありがとうございます。

    質問に書いておけばよかったのですが、動的リンクではできることを確認しています。

    以前はVisual Studio 2008とWindows 7 SDKを使っていて、その環境では静的リンクができていたので、なぜVisual Studio 2015だとできないのかと疑問に思ったことから質問しました。

    2016年4月1日 13:19
  • ありがとうございます。

    #pragma comment(lib, "UxTheme.lib")

    は試してみましたが、特に変わらないようでした。

    2016年4月1日 13:20
  • 原因は、
    BeginPanningFeedback、UpdatePanningFeedback、EndPannigFeedback 関数は C++ リンケージで定義されているのですが、ヘッダーファイル「uxtheme.h」が C リンケージで読み込まれているからです。この場合、dwmapi.lib をリンクしても、前述の関数シンボルが見つからなくなります。

    私の環境ではインクルードの順序は下記のようになっていました。

    "[プロジェクトフォルダ]\stdafx.h"
    "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxwin.h"
    "C:\Program Files (x86)\Windows Kits\8.1\Include\um\dwmapi.h"
    "C:\Program Files (x86)\Windows Kits\8.1\Include\um\Uxtheme.h"

    上記の dwmapi.h の中で

    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    <中略>
    
    #include <uxtheme.h>
    
    <中略>
    
    #ifdef __cplusplus
    }
    #endif

    というような感じで include されていました。

    1つの解決方法は、
    MFCのヘッダー中で Uxtheme.h をインクルードさせないように _UXTHEME_H_ を定義し、その後自分で関数の宣言を行います。以下のように stdafx.h の中の

    #include <afxwin.h>         // MFC のコアおよび標準コンポーネント

    の部分を下記のように置き換えます

    #define _UXTHEME_H_
    
    typedef struct _MARGINS
    {
    int cxLeftWidth;      // width of left border that retains its size
    int cxRightWidth;     // width of right border that retains its size
    int cyTopHeight;      // height of top border that retains its size
    int cyBottomHeight;   // height of bottom border that retains its size
    } MARGINS, *PMARGINS;
    
    #include <afxwin.h>         // MFC のコアおよび標準コンポーネント
    
    BOOL WINAPI
    BeginPanningFeedback(
    __in HWND hwnd);
    
    BOOL WINAPI
    UpdatePanningFeedback(
    __in HWND hwnd,
    __in LONG lTotalOverpanOffsetX,
    __in LONG lTotalOverpanOffsetY,
    __in BOOL fInInertia);
    
    BOOL WINAPI
    EndPanningFeedback(
    __in HWND hwnd,
    __in BOOL fAnimateBack);
    
    // Uxtheme.h はインクルードせず Uxtheme の使いたいAPIは自分で宣言して下さい。

    ※構造体 _MARGINS を定義しているのは afxwin.h の中で使われているからです。

    ちなみに、VS2008 を確認してみましたが、afxwin.h の中でリンケージ指定なしで Uxtheme.h がインクルードされていました。リンクエラーにならなかったのはそのためですね。なぜ今のような設定になっているか知る由はありませんが、不具合とも取れますね。
    Uxtheme の中の3つ関数 BeginPanningFeedback、UpdatePanningFeedback、EndPannigFeedback 以外は C リンケージで定義されているので他の Uxtheme 関数のリンクは既定でも普通にリンクできました。


    以上参考になりましたら幸いです。





    • 編集済み kenjinoteMVP 2016年4月3日 3:22
    • 回答としてマーク syaki 2016年4月4日 0:44
    2016年4月2日 10:57
  • ありがとうございました。

    無事にリンクすることが出来ました。

    標準のライブラリだったのであまり疑っていなかったですが、少しは注意をもって疑ってみることも必要なのでしょうね。

    本音は何も考えずにafxwin.hをインクルードするだけですべて面倒を見てくれることなのですが・・・

    2016年4月4日 0:46