タイトルバーなしのウィンドウの作成方法は?

[戻る]
MK [E-Mail] 2003/02/28(金) 08:50:34
ダイアログではなくメインウィンドウのタイトルバー及びフレームも無くした
クライアント領域のみにする方法を教えて下さい。

また、そのようにした時に、真っ白いクライアント領域をデスクトップ一杯の
大きさに出来るのでしょうか?

ご存知の方よろしくお願い致します。

環境 WIN98 VC++6.0 MFCにて

sugar 2003/02/28(金) 09:16:50
> ダイアログではなくメインウィンドウのタイトルバー及びフレームも無くした
> クライアント領域のみにする方法を教えて下さい。
> 
CWndから派生させたクラスを定義して、アプリケーションクラスのInitInstance()内で
生成させることになると思います。
アプリケーションウィザードが勝手に生成するコーディングは、不要になるわけです。
タイトルバーを持つか持たないかは、そのウィンドウにWS_CAPTIONスタイルが
含まれているか、ということになります。

> また、そのようにした時に、真っ白いクライアント領域をデスクトップ一杯の
> 大きさに出来るのでしょうか?
> 
単に、そのウィンドウのサイズをデスクトップの大きさにすればよろしいかと。

MK [E-Mail] 2003/02/28(金) 09:41:13
sugarさん 早々の回答有難う御座います。

実はまだ初心者で、最近ようやくVC++が判り始めました。

おっしゃっていることの雰囲気はわかります。
(というかまったく判らないと言う程の超初心者ではありません)

ということで、もう少し詳細或いは参考になるサイト等
教えていただけるとありがたいです。

>> また、そのようにした時に、真っ白いクライアント領域をデスクトップ一杯の
>> 大きさに出来るのでしょうか?

正確にはデスクトップ以上にできるか?ということです。



無理なお願いでしたら、無視してください。
今後とも宜しくお願いします。

Shimura 2003/02/28(金) 10:33:21
CFrameWnd::PreCreateWindow() を処理すりゃいいと思うが?
「PreCreateWindow」で検索してごらん。

>正確にはデスクトップ以上にできるか?ということです。
好きなだけ大きくなります。

dairygoods 2003/02/28(金) 10:44:18
>ダイアログではなくメインウィンドウのタイトルバー及びフレームも無くした
>クライアント領域のみにする方法を教えて下さい。

リソースエディタでダイアログのプロパティを開いて、
「スタイル」の「境界線」を「しない」に変更するのでは駄目ですか。

sugar 2003/02/28(金) 11:39:08
dairygoods さんの方法は、確かにシンプルで簡単ですね(その手があったか)。
ダイアログベースのアプリ作りでいけるわけですから。

もう少し詳細を、ということですが。
@Class WizardでCWndを継承したクラスを生成
AInitInstance()で以下実施

CString sreClassName = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
m_pMainWnd = new CHogeWnd;
m_pMainWnd->CreateEx(0, sreClassName, "", WS_POPUP|WS_VISIBLE, 
                                               0, 0, 100, 60, NULL, NULL);

とりあえず縁なしウィンドウは生成できます。
※WM_PAINTの処理とかは、別途必要になります。

wood 2003/02/28(金) 11:45:06
http://www.expertmg.co.jp/html/cti/vctips/
ここの「非矩形ウィンドウの作成」これのことですかね

Shimura 2003/02/28(金) 12:01:06
>確かにシンプルで簡単ですね(その手があったか)。
「ダイアログではない」というのが質問者の前提だと思うが。:-p

MK [E-Mail] 2003/02/28(金) 13:04:27
皆さん回答ありがとう御座います。

Shimuraさんがおっしゃっているように、「ダイアログではない」というのが前提です。
Shimuraさんの方法が取っ付き易かったのでTRYしました。

1.ツールバーは、プロジェクト作成時のウィザードに従い、削除できました。
2.メニューバーは、以下で消せました。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
     ・
     ・
     ・
    cs.hMenu = NULL;//■メニューバーを消す
    return TRUE;
}

3.あとはタイトルバーとフレームです。

そこまで出来たのなら、あとはここをこうするだけだと教えていただける
方がいましたら、よろしくお願いいたします。

またその他の方の方法も後からTRYして結果を報告します。
(まだすぐやれるほどの技能がないため、勘弁ください)

MK [E-Mail] 2003/02/28(金) 13:20:20
以下でメニューも消えました。あとフレームのみです。

BOOL CxxxApp::InitInstance()
{

・
・
・

//■ここから追加
    // ウィンドウが表示(ShowWindow)される前にWS_CAPTIONスタイルを削除
    m_pMainWnd->ModifyStyle(WS_CAPTION, 0, 
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | 
SWP_FRAMECHANGED);
//■ここまで追加    

    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();
    
    return TRUE;
}

Shimura 2003/02/28(金) 13:26:16
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
   ゥゥ・
    cs.style = WS_POPUP;
    cs.x = cs.y = 0;
    cs.cx = ::GetSystemMetrics( SM_CXSCREEN);
    cs.cy = ::GetSystemMetrics( SM_CYSCREEN);
   ゥゥ・
    return TRUE;
}

Shimura 2003/02/28(金) 13:27:14
化けた。X-(
   ゥゥ・ <----・・・・

MK [E-Mail] 2003/02/28(金) 15:22:29
Shimuraさん 出来ました。
有難う御座います。とりあえず報告です。

MK 2003/02/28(金) 21:02:03
皆さん いろいろ教えていただき有難うございました。

ダイアログではなくメインウィンドウでの質問でしたが、ダイアログであれば容易に
実現できることが分かって大変参考になりました。

今回はShimuraさんのやり方で実現できまし・・・・・と思っていたら、
良く見ると画面の周りにフレームらしきものが残っていました。

サイズダウンしてみるとフレームが消えていません。
ということで、分かる方がみえましたらお願いします。

sugar 2003/02/28(金) 22:01:51
ウィンドウの幅、高さをスクリーンサイズより数ピクセル分大きい値を設定し、
ウィンドウの座標を(0, 0)ではなく、マイナスの値にしてみてはどうでしょう?

例えば...
    cs.x = cs.y = -4;
    cs.cx = ::GetSystemMetrics( SM_CXSCREEN) + 8;
    cs.cy = ::GetSystemMetrics( SM_CYSCREEN) + 8;

MK 2003/02/28(金) 22:13:00
sugarさん 回答ありがとうございます。

実は最初のほうでsugarさんに教えていただいた方法のみまだTRYしていません。
せっかく詳細ということで教えていただいたのですが、私には少しまだ難しそうで
すぐには手を付けれません。

で、今回のアドバイスはすでに実行済みで目的が達成できることは確認しました。
しかしながら、ダイアログベースであればプロパティをいじるだけで簡単に達成できて
しまします。メインウィンドウは出来ないではちょっと悔しいです。

今もネット上を探していましたが、同様な質問はいくつかあるのですが、解決にいたった
サイトは有りませんでした。また、解決案はここを見よという回答はありましたが、リンク先
が消えていました。

分かる人お願いします。

Shimura 2003/02/28(金) 23:39:59
>メインウィンドウは出来ないではちょっと悔しいです。
できるよ。

>良く見ると画面の周りにフレームらしきものが残っていました。
CMainFrame::PreCreateWindow() のなかで、CFrameWnd::PreCreateWindow() を呼び出し
てるでしょ?
その場合は、

cs.dwExStyle &= ~WS_EX_CLIENTEDGE;

も追加しなくちゃダメです。理由は、CFrameWnd::PreCreateWindow() の定義を見れば
イッパツ。

kazuma 2003/02/28(金) 23:48:08
ビューのほうの WS_EX_CLIENTEDGE もはずさないと駄目ですよ。

kazuma 2003/02/28(金) 23:51:15
> ビューのほうの WS_EX_CLIENTEDGE もはずさないと駄目ですよ。

ごめんなさい。
私がイメージしてたのは MK が考えてるのとはちょっと違うかも。

Shimura 2003/02/28(金) 23:57:24
>で、今回のアドバイスはすでに実行済みで目的が達成できることは確認しました。
>しかしながら、ダイアログベースであればプロパティをいじるだけで簡単に達成できて
>しまします。メインウィンドウは出来ないではちょっと悔しいです。

補足というか、何というか。
MFC を使ってるんなら、MFC が内部で何をやってるのかも探ってみなきゃダメです。
簡単なエディタならものの5分で作れちゃうのが MFC だけど、逆に変化球を打とうとす
れば一筋縄でいかないのも MFC です。
試しに、今作ってるアプリケーションを MFC を使わずに書いてみてごらん。
そうすれば、MFC の良さも MFC の悪さも、便利な点も不都合な点も、いろいろと
見えてくるハズです。

そして再度 MFC に戻ってみると、ダイアログベースにかかわらず
「簡単に達成できてしまう」と感じるコトでしょう。:-)

kazuma 2003/03/01(土) 00:00:19
たびたびすんません。
「真っ白いクライアント領域をデスクトップ一杯の大きさに」
したいならやっぱり、
「ビューのほうの WS_EX_CLIENTEDGE もはずさないと」いけません。

# 先ほどの書き込みで MK さんの名前に敬称を付けるのを忘れていました。
# ごめんなさい。

Shimura 2003/03/01(土) 00:02:30
>ビューのほうの WS_EX_CLIENTEDGE もはずさないと駄目ですよ。
ビューのぼうもいじってるとすれば、ハズすべきは WS_EX_CLIENTEDGE ではなく
WS_BORDER ですな。

kazuma 2003/03/01(土) 00:10:22
> >ビューのほうの WS_EX_CLIENTEDGE もはずさないと駄目ですよ。
> ビューのぼうもいじってるとすれば、ハズすべきは WS_EX_CLIENTEDGE ではなく
> WS_BORDER ですな。

ほんとだ、
PreCreateWindow でやるときは WS_BORDER をはずさないと駄目みたいですね。
(CView::PreCreateWindow で何やらやっている。)

後からやるときは WS_EX_CLIENTEDGE をはずせば OK です。

MK 2003/03/01(土) 08:48:53
皆さんおはようございます。今日も朝5:00からがんばっています。
またまた回答を頂き、やった〜と大喜びでTRYしたのも束の間、出来ませんでした。

大変ご迷惑をおかけします。
また、厳しいVCのQ&Aの世界で親切且つ罵倒せずにこれまで回答頂き有難うございます。

そろそろ諦めようかとも思いましたが、最後に恥をしのんでもう一度質問させてください。

<Shimura 2003/02/28(金) 23:39:59>

>>メインウィンドウは出来ないではちょっと悔しいです。
>できるよ。
そうですよね。出来なきゃ詐欺だ。

>>良く見ると画面の周りにフレームらしきものが残っていました。
正確にはフレームでは無くクライアント領域の3Dのエッジだと思います??

>CMainFrame::PreCreateWindow() のなかで、CFrameWnd::PreCreateWindow() を呼び出し
>てるでしょ?その場合は、
すみません。まだ会話についていけるだけの力がありません。
↓これのことでしょうか?
if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;

>cs.dwExStyle &= ~WS_EX_CLIENTEDGE;も追加しなくちゃダメです。
以下のように追加しましたが、だめでした。追加の仕方が変?

  cs.style = WS_POPUP;
  cs.dwExStyle &= ~WS_EX_CLIENTEDGE; <---■追加しました
    cs.x = cs.y = 0;
    cs.cx = 100;//::GetSystemMetrics( SM_CXSCREEN);
    cs.cy = ::GetSystemMetrics( SM_CYSCREEN);

>理由は、CFrameWnd::PreCreateWindow() の定義を見ればイッパツ。
定義を見ようとしましたが見ることが出来ませんでした。
CFrameWnd::PreCreateWindow()を検索しましたがプログラムのコードの中には定義らしい
ものは見つけられませんでした。
とここまで、質問を書いたところでちょっと待てここまで恥をさらして良いものかと
ヘルプを見よと言っているんだなと気づき、さらにこのヘルプは見覚えがあるぞどこを見れだ
いいんだと思ってさがしたら、拡張スタイルが一番下にあるではないですか。

ということで、cs.dwExStyle &= ~WS_EX_CLIENTEDGE;の意図はわかりましたが、
ウィンドウの境界の縁の3Dは消えませんでした。 

>補足というか、何というか。
ことばのご配慮感謝します。

>試しに、今作ってるアプリケーションを MFC を使わずに書いてみてごらん。
>そうすれば、MFC の良さも MFC の悪さも、便利な点も不都合な点も、いろいろと
>見えてくるハズです。
SDKの勉強も数ヶ月やりました。といっても読むだけでコードを直接打ち込んないので
身についてはいませんが。と言うことで今ようやくMFCにTRY出来るようになった
ところです。仮にSDKが理解できていたとしても、MFCのとっつき難さをあらためて
クリアする必要があると感じてます。
(SDKの勉強は十分今役立っています。だだMFCに移行するときにはMFC独自の最初の
高い敷居を超える必要がある。と私は感じています。Shimuraさんのアドバイスを否定するもの
では決して有りません)

MK 2003/03/01(土) 09:18:20
kazumaさん こんにちは、前文が長くなってしまったので、分けました。
いろいろアドバイス有難うございます。


>「ビューのほうの WS_EX_CLIENTEDGE もはずさないと」いけません。
ビューのほうは、プロジェクト作成時のウィザードにより作成された状態からいじっては
いませんが、ビューがなにかしらの影響を与えているのならと思い
以下を削除しましたがエッジは消えませんでした。
↓
BOOL CABCView::PreCreateWindow(CREATESTRUCT& cs)

# 先ほどの書き込みで MK さんの名前に敬称を付けるのを忘れていました。
# ごめんなさい。
教えてもらう身なので我慢、我慢というか、文章から付け忘れとすぐ分かりました。
いつもアドバイス有難うございます。

>(CView::PreCreateWindow で何やらやっている。)
この辺の意味を理解できるだけの力がまだありません。
コードの中にCView::PreCreateWindowがあると言うことは、当然CViewでもPreCreateWindow
をよびだして何やらやっているということで良いのでしょうか?
今後のことも考え教えていただけるとありがたいです。

<ここからは独り言>
当然、私のようにメニューバーやフレームを取りたいと思う人はたくさんいて、
ネット上でも質問している人はたくさんいます。
でも、解決した結果は見つけれません。
以下調査結果
1.分かりましたやってみます。で終わっている。
2.出来ました。とかいてあるがどうやったら出来たのか書かずに終わっている。
3.著名なサイトでまさにフレームは消えるがエッジが残るとの質問に著名な人本人が
  私にも分かりません。(笑)で終わっていた。
4.ネット上あるいは本にエッジなしのウィンドウのコードはあるが、SDKか
  ダイアログベースで書かれていて、MFCのメインウィンドウの例は見つけられなかった。
  

MK 2003/03/01(土) 09:44:12
[[解決]]
とうとう出来ました。
OnCreateを追加し、以下のとおりです。

int CXXXView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // TODO: この位置に固有の作成用コードを追加してください
    ModifyStyleEx(WS_EX_OVERLAPPEDWINDOW,0,0);////■これを追加

    return 0;
}

Shimura 2003/03/01(土) 10:34:29
とりあえず、解決されたというコトなので、最後の補足をば。

>↓これのことでしょうか?
それのコトです。で、CFrameWnd::PreCreateWindow() の定義を見ると

BOOL CFrameWnd::PreCreateWindow( CREATESTRUCT& cs)
{
    ・・・・
    cs.dwExStyle |= WS_EX_CLIENTEDGE;
  ・・・・

    return TRUE;
}

なんてコトをやってるのがわかると思います。だから、これを呼び出した後には、

    cs.dwExStyle &= ~WS_EX_CLIENTEDGE;

して、拡張スタイルを消してやらなきゃダメなんです。これが先述した「理由」という
ヤツ。「定義を見よ」とは、この、CFrameWnd::PreCreateWindow() のコードを見よ、
ってコト。(関数の「定義」とか「宣言」とかいう言葉を聞いたコトあるよね?)

>以下を削除しましたがエッジは消えませんでした。
>↓
>BOOL CABCView::PreCreateWindow(CREATESTRUCT& cs)

これを消しちゃうと、エッジは消えません。なぜなら、CView::PreCreateWindow() の
なかで、WS_BORDER スタイルを WS_EX_CLIENTEDGE スタイルに変更する、なんてコト
をやってるから。
これをさして、kazumaさんは↓こうおっしゃっているワケ。
>(CView::PreCreateWindow で何やらやっている。)

だから、CABCView::PreCreateWindow() ではこうなります。

BOOL CABCView::PreCreateWindow(CREATESTRUCT& cs)
{
    cs.Style &= ~WS_BORDER;              // (1)
    if ( !CView::PreCreateWindow( cs)) return FALSE;

    cs.dwExStyle &= ~WS_EX_CLIENTEDGE;   // (2) 

    return TRUE; 
}

※ (1) と (2) はどちらか一方でよい。これが kazumaさんのおっしゃっている

>後からやるときは WS_EX_CLIENTEDGE をはずせば OK です。

にもつながってくる。もちろん、C**View::OnCreate() でコレをはずしても特に問題は
ない。(「一度つけておいて、すぐにはずす」という、コード的な回り道はあるけど
ね)。

><ここからは独り言>
独り言にリプライするのも何ですが。
質問だけしておいて、後始末をしない質問者が多いのは僕も感じてます。
ただ、そういう人には何を言ってもムダだろうから、何も言いません。
後々に自分がソンをするだけです。
願わくば、MKさんがそうならないコトを。

MK 2003/03/01(土) 23:45:43
Shimuraさん 今回のことではいろいろお世話になりました。

解決ということで終わりにしたかったのですが、最後の補足を受け、また
私と同様の悩める初心者のために敢えて書きます。と言うか自分が納得したいから・・

他のサイトでも過去に同様のやり取りをしているところを見つけました。

やはり回答者はShimuraさんと同じことをアドバイスしているのですが、質問者のほうは
うまくいかないと言って困っておりました。実は私もアドバイスどおりではうまくいきません。

おっしゃていることの意味は分かりますし、私もそう思うのですが事実うまくいきません。
ということで、探しまくって、そう言うときはこうしろと言うサイトを見つけようやく解決に
いたったしだいです。

多分両者の間に何らかの思い違いなり環境の違いがあると思われます。

アドバイス通りではうまくいかないけれど、MK(さん)はうまくいったのだろうか
と悩んでいる他の初心者のために敢えて書きました。

MK 2003/03/02(日) 00:15:43
Shimuraさん 申し訳ありませんでした。

教えていただいた情報のみでうまくいきました。

勘違いは私のほうでした。
只いじりすぎて良く分からなくなってしまいました。
とりあえず訂正のメールです。

最後にひとつ。
前にも書きましたが、以下の定義を見よと言うことで探しましたが、ウィザードが作った
コードの中には見つけれませんでしたので、私はヘルプで調べました。

コード見よといわれましたが、プロジェクトの中のどこかにコードがあるのですか?



>CFrameWnd::PreCreateWindow() の定義を見ると

>BOOL CFrameWnd::PreCreateWindow( CREATESTRUCT& cs)
>{
>    ・・・・
>    cs.dwExStyle |= WS_EX_CLIENTEDGE;
>  ・・・・

>    return TRUE;
>}

>なんてコトをやってるのがわかると思います。
>「定義を見よ」とは、この、CFrameWnd::PreCreateWindow() のコードを見よ、
>ってコト。(関数の「定義」とか「宣言」とかいう言葉を聞いたコトあるよね?)

Shimura 2003/03/02(日) 01:15:22
>コード見よといわれましたが、プロジェクトの中のどこかにコードがあるのですか?
MFC のソースコードです。VC++6.0 ならば、デフォルトの場合、

\Program Files\Microsoft Visual Studio\VC98\MFC\SRC

にあります。なければ、インストール時に「インストールしない」を選択されているの
で、今後のためにも追加インストールしておくといいです。

MK 2003/03/02(日) 07:17:44
Shimuraさん おはようございます。
今日も朝からがんばっております。

回答本当に有難うございます。最初の頃から上記の意味は分かっても、実際どこに書いてあるか
分からずもやもやしてました。

てっきりMFCのなかの見ることの出来ないファイルに書かれているものかと思っていました。

で、さっそく感謝と核心に迫れる喜びで仰せの場所を探してみたら、XXX.cppが
たくさん有るではないですか。で、どれを見れば良いの、また聞いてみるか。でもこれ以上
聞けないよな。

ということで、自力でようやく見つけました。
Winfrm.cppに以下の記述がありました。

分かってしまうと簡単なことでも、分からない人にはわからないんですよね。
これでまた大きく前進できました。ここまでお付き合い頂き本当に有難うございました。

教えていただいたことを使ってデスクトップ上にランダムな色と大きさの四角をひたすら描くプ
ログラムを完成させることが出来ました。
自分で作った初めてのMFCプログラムといえると思います。

このプログラムは冬休みに、有名な猫でも〜で勉強してたときに見かけておもしろいと思ってい
たのに、今探そうとすると何時間かけても見つけ出すことが出来ず。とうとう自分で作ってみよ
うと思い立って作ったものです。(スクリーンセーバーなら見つけたが、自分がみたものはスク
リーンセーバーのように画面をいったん黒くするのではなく、画面上に直接絵を書いていたと思
う)
ようやくVC++の何も分からない闇の世界からここまで来ることができました。

再度ありがとうございました。今後ともよろしくお願いいたします。


<以下が見つけたコード>
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
    if (cs.lpszClass == NULL)
    {
        VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
        cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW 
background
    }

    if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
        cs.style |= FWS_PREFIXTITLE;

    if (afxData.bWin4)
        cs.dwExStyle |= WS_EX_CLIENTEDGE;

    return TRUE;
}

古いスレッドには追加発言できません。