VisualStudio2008にてMDIアプリケーションを作成して、ビューを開き最大化にした状態
でビューを閉じるとMDI枠のヘッコミ?クライアントエッジ的な表示がなくなるんです。
最大化させないで閉じるとなくならない。
これはCMDIFrameWndExを使うときは仕方ないのでしょうか?
CMDIFrameWndExを使わないとこの症状は起きません
何か回避策があれば、お手数ですが教えていただけませんか?
ちなみに2010でも同じ症状がでるんです…
自分しては「バグ」の判定ですね。
Spy++で見ればすぐにわかりますが、その操作をするとMDIClient
の WS_EX_CLIENTEDGE スタイルが外れてしまいます(笑)。
以後、復活することはありません。はっきりいってまぬけです。
自分でコードすれば WS_EX_CLIENTEDGE スタイルを付け直すことも
できますが、面倒なのでやってません。
直接は関係ありませんが、メニューバーのメニューのショートカットキー
の表示(ex. ファイル(F))の(F)の部分のアンダースコアも表示されませんよね
(しくしく)。
もとい。アンダーラインですねorz。
バグですか…
CMDIFrameWndExのm_hWndMDIClientをサブクラス化できないのも、やっぱりバグなんでし
ょうかね、ちょっとがっかりですね
それともやり方が悪いんでしょうかね
CMFCCaptionBarの画像を割り当てないと(SetBitmap)しないとXボタンがなくなっちゃう
のもバグっぽいですね
RecalcLayoutをオーバーライドしてコチョコチョしないと具合悪いですね
Visual2010で改善されなかったぽいですし, 改善されないということは仕様ということ
ですかね
あ、解決ということで、ありがとうございます
RecalcLayout()を操作する必要はありません。
バグって言えばバグですよね。
原因は
CMDIChildWnd::UpdateClientEdge()です。
子MDIが閉じる時にこの関数が呼ばれますが、この関数は子MDI
が最大化する場合に、WS_EX_CLIENTEDGEを外し、それ以外では
付けます。
ただし、閉じる時には対応できていないので外れた状態のままになります。
このことから、最大化を外してあげれば解決します。
# 子MDIが複数ある場合+最大化の場合はその必要はありません。
子MDI(CMDIChildWnd(Ex))のWM_CLOSEを処理し、以下のようにすれば解決します。
必要であれば、WS_EX_CLIENTEDGEが付いていない時の条件も加えても良いと思います。
void CHogeChildFrame::OnClose()
{
CMDIFrameWnd* pFrameWnd = dynamic_cast<CMDIFrameWnd *>( AfxGetMainWnd() );
ASSERT_VALID(pFrameWnd);
if( (GetStyle() & WS_MAXIMIZE) &&
( ::GetWindow( ::GetWindow( pFrameWnd->m_hWndMDIClient, GW_CHILD ),
GW_HWNDNEXT ) == NULL )){
ModifyStyle( WS_MAXIMIZE | WS_VISIBLE, 0, 0 );
}
__super::OnClose();
}
参考まで
追記。
> 仲澤@失業者さん
>自分でコードすれば WS_EX_CLIENTEDGE スタイルを付け直すことも
>できますが、面倒なのでやってません。
この処理を閉じる時にModifyStyleEx()で付けてあげても、
結局CMDIChildWnd::UpdateClientEdge()が呼ばれて外されてしまいます。(T.T)
本件について、あまり真剣に考えるつもりはないのですが、
まぁ、暇つぶしにやってみると。
まず、適当なタイミングのメッセージがわからなかったので、
メインフレームのWM_PAINTのコードに下記のコード
BOOL res =::EnumChildWindows( m_hWndMDIClient, EnumFunc, ( LPARAM)0);
if( res == FALSE){
LONG_PTR Style =::GetWindowLongPtr( m_hWndMDIClient, GWL_EXSTYLE);
if( 0 ==( Style & WS_EX_CLIENTEDGE)){
CRect rc;
GetClientRect( &rc);
Style |= WS_EX_CLIENTEDGE;
::SetWindowLongPtr( m_hWndMDIClient, GWL_EXSTYLE, Style);
::SetWindowPos( m_hWndMDIClient, NULL, 0, 0, rc.Width(), rc.Height(),
SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE);
::RedrawWindow( m_hWndMDIClient, NULL, NULL,
RDW_ERASE | RDW_FRAME | RDW_UPDATENOW);
}
}
をつっこんでやると、なんとかなりますよね(vv;)。
まぁ、正確なタイミングがわかったら、自分も対応したいとおもいます。
ちなみにEnumのコールバックは
BOOL CALLBACK EnumFunc(
HWND hwnd, LPARAM lParam)
{return FALSE;}
でよしっと。
色々考えてくださってありがとうございます
えっと,少々強引ですが CMainFrame(:CMDIFrameWndEx)の中で
GetWindowLongにて現在のExスタイルを取得してWS_EX_CLIENTEDGEとのアンドが0
ならばModifyStyleExで足すという処理をOnTimer内でポーリング的に実行させたのです
がダメでした
m_wndClientArea(:CMDIClientAreaWnd)という子がCMDIFrameWnd内のm_hWndMDIClientを
サブクラス(SubclassWindow)していて,この子が悪さをしているっぽいです
m_wndClientAreaをサブクラスかすれば何とかなりそうですけど,m_hWndMDIClientをサブ
クラス化しているm_wndClientAreaをサブクラス化させる方法は知りません,というかそ
んな方法はないのでは?
ダミーでドッカブルペインをクリエイトさせて追加させて,そして常に非表示とすると
OKなんですが…
仲澤@失業者さんの方法だと確かにできますね
TimerでできないのはWM_PAINT時に毎回WS_EX_CLIENTEDGEをはずしにきているんですか
ね?
やな感じですね
xxxEx系の新しいクラスはおかしなとこいっぱいですね
ごめんなさいウソでしたTimerでもできます
スタイル変更後,SetWindowPos忘れてました...
バグや改善提案についてはぜひこちらにフィードバックしてください。
https://connect.microsoft.com/VisualStudioJapan/Feedback
> メニューバーのメニューのショートカットキーの表示(ex. ファイル(F))の(F)の部分
> のアンダースコアも表示されませんよね(しくしく)。
それは最近の Windows の共通仕様では? OS は何でしょうか。
aetosさん
>> メニューバーのメニューのショートカットキーの表示(ex. ファイル(F))の(F)の部分
>> のアンダースコアも表示されませんよね(しくしく)。
>それは最近の Windows の共通仕様では? OS は何でしょうか。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+201007/10070007.txt
これのことです。
> これのことです。
MFC のソースまでは追いかけていませんが、Windows Server 2008 R2 x64 + VS2010
Ultimate で試したところ、メニューを縦にしても下線は表示されませんでした。
また、同環境にて、本題である
> MDI枠のヘッコミ?クライアントエッジ的な表示がなくなるんです。
の方も再現できません。