MFC相談室 mfc23d.dll [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
>>281
ダイアログをCreateする時、親ウィンドウ(省略時=NULL)を指定していないから、
アプリケーションのメインウィンドウ(=AfxGetMainWnd())が、親ウィンドウが
になっているからでは?
CDialog::Create(CWnd::GetDesktopWindow())
とかでいけるはず。 MFCとは関係なく、Windows APIでは、所有ウィンドウ
(Owner Window)と、親ウィンドウ(Parent Window)は別管理。 MSDN見ても解決しないのでお願いします。
CMFCColorDialogで作成した色選択ダイアログの動きが少しおかしいです。
どれかの色(六角形)を選択すると[OK]ボタンのフォーカスが当たり、再度
別の色を選択するとフォーカスが外れるんですが、仕様でしょうか?? >>284
VS2008のNewControlsサンプルではそういう動作は見られないけど、
再現できるサンプルでもありますか? >>285
わざわざ試していただいてありがとうござます!
こちらの環境、Windows10、VisualStudio2017なのでこれが原因っぽいです。
古いVisualStudioで試してみます。
業務アプリなのでサンプルは出しにくいです。申し訳ないです。 >>282
おお、今頃ですが、ありがとうございました
これでAlt+Tabでもモードレスウインドウが出てくるようになりました ! 今まで、VC++6.0でずっとやってきました。特にそれで問題なかったからですが、意を決して、
Visual Studio 2017をインストして、古いソースコードを移植しようと思っています
VS2017に古いVC++6.0のdswファイルを読ませたのですが、うまくj変換できないようですが、どうしたら良いでしょうか
VC++6.0からの変換は出来ませんか ワークスペースはソリューションに変わった。新しくソリューションファイルを作って、そこにC/C++のファイルを追加してビルドだ。 インクルードファイルとかいろいろエラーがたくさん出てきたよ
これ相当無理っぽい??? 取りあえず、簡単に比較するために、VC++6.0でMFCのSDIのデフォルトを作りました
それと比較するため、VS2017でC++のWindowsデスクトップのデスクトップアプリケーションのデフォルトを作りました
すると、VS2017の方はMFC自身を使わないバージョンなのかな、CMainFrmとかIMPLEMENT_DYNCREATEとかなくて
VC6.0++のMainFrm.cppとかを2017の方に持ってきてコンパイルしたらCMainFrmが定義されてないとか
ずらっとたくさん出てきます MFCに対応したプロジェクト/ソリューション設定じゃないとダメかも >>293
VS2017で、それを探してるのですが見つからないのですよ
MFCには対応してるのですよね。2015かそれ以前にはすでに対応してると聞いていたのですが
MFCを使ったデフォルトのコード生成はしてくれないとか??? w Visual C++の中にMFCがある。Visual C++という項目がなければ、インストールが間違っている。 >>295
メニューのファイルから新規作成、プロジェクトを選ぶと、その中にVisual C++はちゃんとありますよ
で、そこでWindowsデスクトップアプリケーションを選んでデフォルトを作ると、コードはSDKみたいなコードを吐きます
で、Windowsデスクトップウィザードってのがあったので、今これを選択してみたのですが、
アプリケーションの種類をコンソールにすると、その右にあるMFCのチェックボックスが有効になるのですが 続き
Windowsアプリケーションってのを選ぶと、MFCのチェックボックスが使用不可になってしまいます MFCアプリが作れないなら、インストールで追加するしかないぜ。 おいおい、なんだこれ
VS2017で、新規作成、プロジェクトで、Windowsデスクトップウィザードで
コンソールアプリケーションでMFCをチェックしてデフォルトのコードを自動生成してみました
そしてソリューションのビルドしたら、CWinAppが定義されてないとかエラーがわんさか出てきたぞ
おいおい、デフォルトの自動生成コードもビルド出来ないじゃん >>299
おや、そこが違う。 私のは、
visual C++の下に
Windowsデスクトップ
クロスプラットフォーム
MFC/ATL
テスト
その他
Extensibility
ってなってて、 MFC/ATLのところは
ATLプロジェクト
ってのだけがあります 何かインストを失敗してるのかなあ。 あるいはインストするときに何をインストするのかチェックがあったんだが
それを間違えてるのか。 でも俺がチェックをしなかったのはモバイル関係のところくらいだったんだよねえ VS2017は頻繁に変更されるもんだから、ちょっと混乱してるみたい。 >>304
ありがとう。
右側の概要ってとこが、私のでは、インストールの詳細になっていて、
MFCとATLのサポート
ってのが私のでは、
x86用とx64用のVisualC++ATL
x86用とx64用のVisualC++MFC
ってわかれていて、ATLの方にだけデフォルトではチェックが入っていてMFCの方のチェックは
デフォルトでは外れていました。
チェックして再インストしてみますねw ただいま、 再インスコ中です
みなさん、 VS2017をインスコするときは、
MFC はデフォルトでは入らない !!!
ことがわかりました
VS2017をインスコするときは、注意しましょう
インスコするとき、オプションをチェックすると入ります、 多分。今やってるところ Qiitaの記事、結構役に立ってるじゃん。責任ある情報技術者なら、Qiitaに記事を書ける程になってもらいたいね。 出来ました。
MFCのインストがちゃんとできて、
MFCアプリケーションでデフォルトのMDI作ってみたら、 あら、すげえ
クラスビューなんかが出てくるのねw おや、新しいバージョンだと、
strcpy( a, b )
で、b に CSringとか出来ないんだね。 前の古いバージョンでは出来たのに
CString で返す関数も、char a[10] とかで宣言したのを、古いバージョンでは、retuen a
って出来たんだが、新しいバージョンではエラーになる。 一旦
CString ret;
ret = a;
ってやって、return ret;
ってやったらエラーが消えた
いろいろと細かい修正しないとダメみたいだねえ 暗黙の型キャストのあいまいさが嫌いな人が存在するらしい。 >>314
いろいろとありがとう。 今日はとりあえずここまでにしておきます >>317
これありがとう。LPCWSTRの関係で、めっちゃ詰まってました >>313
そもそも、CStringはTCHARを扱うクラスなのに、
_tcscpyではなくstrcpyを使っていたのが間違い >>319
今は、_tcscpyを使ってもエラーが出るけどな >>320
それはエラーではなくてセキュリティ上の警告では >>321
そうです。 _sを付けたのを使えって
警告の設定を変更しないとエラーになってコンパイルが通りません
それをプロパティの設定で、Unicodeからマルチバイトに切り替えてコンパイルしたんだけど、どうも
Unicodeのままでうまく切り替わらないようなんですよねえ。 どうなってるのか。 今は時間がないので
またあとでやってみますが >>322
警告だから、それに関してはコンパイルは通る。
他の場所がコンパイルエラーになっているだけかと。 VS2017ですが、新規作成で、MFCアプリケーションで作った時、
新規作成途中に出てくるSDLのチェックをつけて作成したときと、はずして作成したときと両方してみました
すると、SDLつきの時は、_tcscpyはエラーになってコンパイルできませんが、
SDLをはずして新規作成したのものは、エラーにならずにコンパイルできて実行できます
デフォルトはSDLつきなので、コンパイルできません
次に、新規作成して出来上がったプロジェクトで、
メニューのプロジェクトから一番下のプロパティに入って、構成プロパティ、C/C++の全般にある
SDLチェックというところで、はい(/sdl) いいえ(/sdl-)を切り替えてやってみると、
この切り替えが動作せず、SDLのオン、オフが効きません。 プロジェクトの新規作成のときに設定したものが
残っていて、あとからここのプロパティで変更ができないようです
同じように、プロパティの構成プロパティの全般で、文字セットがデフォルトではUnicode文字セットを使用する
になってるのですが、これをマルチバイト文字セットを使用するにしても
Unicodeのままでマルチバイトにならないようです
バグですかねえ? >>324
VisualStudioCommunity2017で試したが、普通に設定が反映されたぞ。
DebugとRelease、x86とx64で設定が別なのに気づいてないとかじゃないか? >>326
できました。多分それです。ありがとうございました
コードの編集画面の上にあるコンボボックスを見ると、Debugとx86になってるのですが、
その状態でプロパティを開くと、なぜか、x64になってました。
なのでプロパティ画面で、上にあるプラットフォームをアクティブ(Win32)に変えると、画面がおかしくなって
びっくりしましたが、画面の再描画ができなかっただけなようで、再びプロパティ画面を出して
アクティブ(Win32)を確認してから、マルチバイトやSDLの変更をしたら、ちゃんと動いたようです
プロパティ画面を開くときは、連動してないので必ず確認してから変更しないといけないということですね
ちなみになんとか誤魔化せないかと思って、 stdafx.h の最初に
#undef UNICODE
#undef_UNICODE
ってやってみたら、コンパイルまでは全部のcppファイルで出来たのですが、リンクで未解決エラーが出て
出来ませんでした さすがにそれはおかしいのでVS2017再インストール推奨 >ちなみになんとか誤魔化せないかと思って
略
>リンクで未解決エラー
MessageBoxA と MessageBoxW とかを自分で書き分けてみると解決するはず MFCのツールバーって、リバーのように、「ツールバーを固定する」の動作はできませんかね。
ユーザーがコマンドを選択したら、その場所から動かすことができなくなるようにしたいのですが。 subclass化してメッセージループトラップしてmoveをにぎりつぶす HWND hWnd はできるけど、
HDC hDC って、別アプリ(別プロセス)に渡して、書き込ませることは出来ないの?
HDC の識別番号が、プロセスごとに別の「名前空間」みたいなことになってるのかな。 GDI objects support only one handle per object. Handles to GDI objects are private to a process.
That is, only the process that created the GDI object can use the object handle.
↑によれば、HDC は、プロセス・プライベートだって、書いてるけど、
たまたますごいことみつけちゃったんだ・・・実は。
みんな知ってる? 実は、PrintWindow(HWND hWnd, HDC hDC, DWORD flag) API を使うと、HDC をプロセスの
垣根を越えて渡せるんだ。プロセスA からプロセス B に HDC を渡す場合、
プロセスA で、PrintWindow() API を呼び出す。hWnd にはプロセスBで作成した
Window の HWND を、hDC には、プロセスAに所属している HDC を渡す。
MFCを使って実験してみると、この場合、プロセスBの hWnd にWM_PRINT メッセージが
来るが、OnPrint() ハンドラが BeginPaint(), EndPaint() を使わずに、メッセージから受け取った
hDC を CDC *pDC に入れて、WM_PAINT の時と同じ OnDraw() を呼び出すらしい。
らしいと言ったのは、もしかしたら、MFCが途中で何らかの手を加えている可能性があるから。
で興味深いのは、この時の pDC->m_hDC の値は、プロセスA のオリジナルの値とは
数値的には異なっていると言うこと。
推定ではあるが、PrintWindow() API を使うと、Windows System が、プロセスA での hDC の
識別番号とは異なる識別番号を、WM_PRINT メッセージのの hDC に与える。
これは、>>337 で書いているとおり、HDC は、process private だから、プロセスごとに
「名前空間」が異なるため、プロセスの垣根を越えるときには、同じ値をそのまま使うことは
出来ないため。
でも、結局、「番号」が変わっているだけで、同じ Device Context を「指している」ので、
効率よく 描画動作を行える。
この API を使えば、プロセスA で用意した実DC や メモリーDC に、プロセスB の OnDraw()
によって直接書き込ませることが出来ることを確認済み。 この話には続きがある。
Ubuntu Linux の Wine Emulator 3.2 で実験してみると、PrintWindow() が上手くいかないらしい。
なので、誰かに直して欲しい、と言うこと。
直してクレクレ。 >>338
さらに実験してみたところ、プロセスA から、プロセスB の HWND に対して、
PrintWindow() した場合、プロセス B には、WM_PRINT も WM_PRINTCLIENT
も送られることなく、WM_PAINT、WM_NCPAINT が送られる。
興味深いことに、MainFrame のような、OVERLAPPEDWINDOW には、
メッセージキューを介すことなく、WM_PAINT、WM_NCPAINT が送られるが、
EditBox などの CHILD WINDOW には、メッセージキューに WM_PAINT が
格納された後、EditBox の WndProc に WM_PAINT、WM_NCPAINT が送られる。
もっと実験してみたところ、普段、PrintWindow() を使うことなく、Winow のサイズ
変更などをして再描画が必要な場合、(スレッド)メッセージキューには
ポストされることなく、直接 WndProc に WM_PAINT、WM_NCPAINT が
送られてくる。
また、PrintWindow() に渡す プロセスA の HDC を、MemoryDC にして、
常に固定のハンドル値を渡してみた。すると、興味深いことに、
プロセスB では、ほぼ毎回異なる値の HDC が渡されることが分かった。
ただし、時々連続して同じ値の HDC が渡されてくる。連続回数は、
2回〜10回くらいまでの開きがある。
なお、PrintWindow() の速度は思ったより遅く、プロセスB側が(敢えて)何も
描画しない場合でも、なぜか、1.3x10^(-4) 〜7.1 x 10^(-3) (sec) 程度かかる。
つまり、50万クロック程度かかってしまう。ただし、有る程度の大きさの
グラフィックを書いても、余り速度は変わらない印象を受けた。環境は書かないが、
余り速くはない 3.0GHz の Dual CPU のマシンでの話。 ウインドウを2枚用意して、片方を表に(上に)表示して、もう片方は裏にして見えないようにしている。で、裏の見えない方を
書き換えて、表のウインドウと入れ替えて、新しい描画のウインドウを出すということをしたいのです
裏メモリに書き込んで一瞬でモニターに出すという普通のやつをウインドウでします
裏でウインドウで書き込むとき、HIDE状態では書き込めないので、MINIMIZEの状態では出来ることがわかったので
そうしているのですが、問題はそれを最大化するときに、どうしても描画に時間がかかるというか、一瞬では出来ないのです
なので、アクティブ化せずに裏で最大化、あるいは、RESTOREする方法を探しているのですが、
APIのShowWindowとかだと、RESTOREもMAXIMIZEも必ずアクティブ化してしまうのですがいい方法はないでしょうか
いろいろとやってみて、2枚のウインドウに違う絵をかいておいて、片方をHIDE、片方をSHOWして、このHIDEと
SHOWと切り替えるってのが一番きれいに切り替わるようなのですが、書き込むとき、HIDEでは書き込めずに
MINIMIZEして書き込まないといけないので、MINIMIZEして書き込んだウインドウを表に出さずに大きくしてHIDE状態に出来れは
いいのですが MFCのSDIアプリケーションで、PCを一定時間操作しなかったときに、
「更新中」のダイアログをDoModal()で出して、内部の情報を更新する動作を作っています。
更新処理はダイアログの中で別スレッドで行っていて、
タイマーで定期的にスレッドを監視して、終わっていたらEndDialog()で閉じます。
他の操作を不可にした上でキャンセルは可能にするために、このように作りました。
ここまでは問題なく動いているのですが、
アプリケーションがアクティブでないときにこの更新処理が走ると、
「更新中」のダイアログが閉じられた後に、アクティブ表示になってしまいます。
表示がアクティブになるだけで、フォーカスまでは奪いません。
二つのアプリケーションがアクティブ表示になってしまう状態です。
不思議に思ってMFCのソースを追いかけたところ、
CFrameWndのOnEnable()やOnActivate()やOnNcActivate()で
WF_STAYACTIVEのフラグを使ってアクティブ表示を強制するような仕組みがあり、
この中の処理を通った結果、アクティブ表示になってしまうようでした。
どうしてWF_STAYACTIVEに引っかかるのかなど、細かい流れは追い切れていませんが、
アクティブでないときに裏でダイアログが出て、その後自動で閉じるような動きを、
CFrameWndは想定していないということになりますでしょうか。
見た目のだけの問題ではありますが、CFrameWndの仕組みを保ったまま、
この現象を回避する方法はありませんでしょうか。 ダイアログの前にアクティブだったウィンドウをアクティブにしてから閉じる VS2019のリリースノートでのMFCへの言及は、廃止予定の機能一覧中にいくつかあるのみ。
MFCをバリバリ使っているわけではないけど、なんか悲しい。 空のソリューションを作って既存のAとBのMFCダイアログベースのプロジェクトを追加して、リソースビューでAにBのダイアログをコピペしたらIDが同じという警告が出た。
AのダイアログからBのダイアログをDoModalで呼び出す内容なんですが、ビルドも実行させても問題ないように見えるが大丈夫なんでしょうか? 数年前に作ったダイアログのコンボボックスの初期値が反映されなくなってたんだが
CComboBox:: SelectStringの第一引数nStartAfterを0から-1にしたら動作した
でもなんでやろ?0でよさげなのに いまやCDCといえばアメリカ疾病対策センター(Centers for Disease Control and Prevention)だね ローカルディスクの中で、MFCのCWinやCViewなどのソースは見られるのですが、
AfxGetApp()のソースコードだけが見つかりません。
どこにあるのでしょうか? デバッグすれば見つかると思う。
多分inline だからヘッダにあると。 >>358
拡張子を指定せずに、MFCのソースを含んだ全てのファイルを検索にかけたけど、
AfxGetApp()の定義だけは見つからなかった。
見落としは有るかもしれないが、当然、*.c, *,cpp, *.h, *.inl は全てチェックした。 >>359
afxwin1.inlのアタマにあるぞ。
afxCurrentWinAppを返してるだけだが。 >>360
GUIのgrepで、ファイルマスク欄に *.imp と入れたつもりが *,imp になってました。
orz KillTimer() という Win32 APIは、MSDN によれば、
The KillTimer function destroys the specified timer.
The KillTimer function does not remove WM_TIMER messages already posted to the message queue.
つまり、既にメッセージキューにポストされてしまった WM_TIMER は、「除去されない」とあります。
ところが、MFC の CWnd::KillTimer() は、MSDN によれば、
Kills the timer event identified by nIDEvent from the earlier call to SetTimer.
Any pending WM_TIMER messages associated with the timer are removed from the message queue.
つまり、どんな pending 状態の WM_TIMER メッセージも、メッセージキューから除去される、
とあります。
となれば、MFC の KillTimer() は、何か自分で処理を付け加えているのかと思って、
MFC のソースを grep検索してみると、AFXWIN2.INL に
_AFXWIN_INLINE BOOL CWnd::KillTimer(int nIDEvent)
{ ASSERT(::IsWindow(m_hWnd)); return ::KillTimer(m_hWnd, nIDEvent); }
となっているだけで、単に Win32 の KillTimer() を m_hWnd に対して呼び出している
に過ぎません。
これはどういうことでしょうか?? そりゃ発行済でキューに入ったメッセージはそのままになる罠
自分で読んでしまえば消えるだけのこと >>363
ただ、WM_PAINT や WM_TIMER は、他のメッセージとは異なる処理を
されています。
Win32のメッセージキューは、1つのキューに見えるものが、OSの内部では
複数本持っているか、描画のDirtyフラグなどでなんらかの特殊な扱いを
しているようです。 WM_PAINTは優先度最も低いので常に後ろに行くってどっかで観た 実際には、WM_TIMER は、WM_PAINT以上に優先順位が低いです。
なので、PeekMessage()しても、他のメッセージがあれば WM_TIMERメッセージを
拾えるかどうかは余り定かではないと思います。
もしかすると、その場合には KillTimer()の処理に置いては、WM_TIMERが
メッセージキューに「ポストされて無い」とみなされるのかもしれません。
解釈が難しいです。 いやー仕事でいじることになったんだけどぜんっぜんわからんわなんじゃこりゃ
独自定義の型山盛りでおまけにドキュメントも少ない。いやこれめちゃくちゃ難易度高くない 俺は昨年からC#のwinformに移行してメチャ楽勝です。
もうMFCに戻りたくないです。
でもthreadで動かすのはこっちの方が分かりやすい。 >>368
仕事でってことだがMFCで書かれた既存のプログラムの更新とかなのかな?
そうで無いなら今更MFCなんか使わないことを強く薦める。
MFC必須と言う事ならお奨めの本は、
「MFCによるWindowsプログラミング」ISBN 475611749X
なんだが、古本でもAmazonで\36,000とかしてる。
https://www.amazon.co.jp/s?k=475611749X
東京在住なら国会図書館にあるみたい
https://iss.ndl.go.jp/books/R100000002-I000002930291-00
自分は、これの前の版の
「MFCによるWindows95プログラミング 」ISBN 4756119158
を今でも使ってる。 だめだー格闘したけどビルドすらできない
どうもvc++6.0以前のやつはvc2005以降とだいぶ違う?変換でエラー出るどころか文法もエラー出まくりでどうしようもならん。古い開発環境なんて無いし 無視したら、当時の脆弱性を認めることにはなるけどな。
あと forのカッコの中で宣言したループ変数のスコープとかも、6の時代とは違ったと思う。 判らないなら VC6 使うべき
上位互換でも VC6 モードにするべき MSDN なら XP も VS6 も入手してるはず ■ このスレッドは過去ログ倉庫に格納されています