質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.34%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

1回答

179閲覧

ウィンドウサイズの制限がうまくいかない

mery

総合スコア28

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

0クリップ

投稿2025/01/05 01:22

実現したいこと

ウィンドウサイズの高さをマウスで小さく変更したときに文字1行分の高さより小さくできないようにしたい

発生している問題・分からないこと

数年前に試したとき(windows7の時だったかもしれない)は以下のソースコードでうまくいったはずなのですがなぜか文字が半分ぐらい隠れるようになっていました。
私の考えではタイトルバーの高さ、枠の高さ、文字の高さのどれかの情報が実際より少なく取得されているのではないかと思うのですが・・・。どうすれば改善できますか?

該当のソースコード

C

1#include <windows.h> 2 3LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 4 5TCHAR szClassName[] = TEXT("myprog"); 6 7 8int WINAPI WinMain(_In_ HINSTANCE hCurInst, _In_opt_ HINSTANCE hPrevInst, 9 _In_ LPSTR lpsCmdLine, _In_ int nCmdShow) 10{ 11 MSG msg; 12 BOOL bRet; 13 WNDCLASSEX wc; 14 HWND hWnd; 15 ATOM atom; 16 17 18 19 wc.cbSize = sizeof(WNDCLASSEX); 20 wc.style = CS_HREDRAW | CS_VREDRAW; 21 wc.lpfnWndProc = WndProc; 22 wc.cbClsExtra = 0; 23 wc.cbWndExtra = 0; 24 wc.hInstance = hCurInst; 25 wc.hIcon = (HICON)LoadImage(NULL, 26 MAKEINTRESOURCE(IDI_APPLICATION), 27 IMAGE_ICON, 28 0, 29 0, 30 LR_DEFAULTSIZE | LR_SHARED); 31 wc.hCursor = (HCURSOR)LoadImage(NULL, 32 MAKEINTRESOURCE(IDC_ARROW), 33 IMAGE_CURSOR, 34 0, 35 0, 36 LR_DEFAULTSIZE | LR_SHARED); 37 wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); 38 wc.lpszMenuName = NULL; 39 wc.lpszClassName = szClassName; 40 wc.hIconSm = (HICON)LoadImage(NULL, 41 MAKEINTRESOURCE(IDI_APPLICATION), 42 IMAGE_ICON, 43 0, 44 0, 45 LR_DEFAULTSIZE | LR_SHARED); 46 47 if ((atom = RegisterClassEx(&wc)) == 0) 48 return FALSE; 49 50 hWnd = CreateWindow(MAKEINTATOM(atom), 51 TEXT("ウィンドウサイズ制限のテスト"), 52 WS_OVERLAPPEDWINDOW, 53 CW_USEDEFAULT, 54 CW_USEDEFAULT, 55 CW_USEDEFAULT, 56 CW_USEDEFAULT, 57 NULL, 58 NULL, 59 hCurInst, 60 NULL); 61 if (!hWnd) 62 return FALSE; 63 64 ShowWindow(hWnd, nCmdShow); 65 UpdateWindow(hWnd); 66 while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { 67 if (bRet == -1) { 68 break; 69 } else { 70 TranslateMessage(&msg); 71 DispatchMessage(&msg); 72 } 73 } 74 return (int)msg.wParam; 75} 76 77//ウィンドウプロシージャ 78 79LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 80{ 81 HDC hdc; 82 PAINTSTRUCT ps; 83 static int cyChar; 84 static TCHAR szMoji[256]=TEXT("ウィンドウサイズの高さを小さくしてもこの文字列が隠れないようにする"); 85 TEXTMETRIC tm; 86 LPMINMAXINFO lpmm; 87 switch (msg) { 88 case WM_CREATE: 89 hdc = GetDC(hWnd); 90 GetTextMetrics(hdc, &tm); 91 cyChar = tm.tmHeight + tm.tmExternalLeading; 92 ReleaseDC(hWnd,hdc); 93 break; 94 case WM_GETMINMAXINFO: 95 lpmm = (LPMINMAXINFO)lp; 96 lpmm->ptMinTrackSize.y = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) * 2 + cyChar; 97 return 0; 98 case WM_PAINT: 99 hdc = BeginPaint(hWnd, &ps); 100 TextOut(hdc, 0, 0, szMoji,lstrlen(szMoji)); 101 102 103 EndPaint(hWnd, &ps); 104 break; 105 case WM_DESTROY: 106 PostQuitMessage(0); 107 break; 108 default: 109 return (DefWindowProc(hWnd, msg, wp, lp)); 110 } 111 return 0; 112}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

GetSystemMetrics関数などの情報を調べなおしたが原因がよくわからなかったです。

補足

Microsoft Visual Studio Community 2019
Microsoft Visual C++ 2019 C言語
WIN32 ユニコードビルド Windows10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

setoppu

2025/01/05 04:32

Windows8辺りからだったか… 最小化/最大化/閉じるのボタンのスタイルが変わったので、 キャプションの縦サイズではうまく収まらなくなったのかも知れません。 AdjustWindowRect()/AdjustWindowRectEx()などで、「クライアント領域のサイズから」境界線込みのサイズを算出するように変更してみてはどうでしょうか? WM_GETMINMAXINFOの時に、 GetClientRect(hWnd, &WndRect); WndRect.bottom = WndRect.top + cyChar; こんな感じでクライアントサイズの縦サイズを表示文字列のサイズにして、 AdjustWindowRect(&WndRect, WS_OVERLAPPEDWINDOW, false); で、フレーム込みのサイズを算出。 lpmm->ptMinTrackSize.y = WndRect.bottom - WndRect.top; として、サイズを制限…という方向で。 なお、ウィンドウが表示される前にもWM_GETMINMAXINFOが 飛んでくる可能性はあるのでそのあたりは要注意…でしょうか? (ブレークポイントなりで確認してください。)
mery

2025/01/05 07:29

回答ありがとうございます。AdjustWindowRectを使う方法に加え、文字の高さを求めるところでtmExternalLeadingを加算しないようにしたら目的の結果を得ることができました。
guest

回答1

0

ベストアンサー

改修案の一例です。これならどうでしょう。WM_GETMINMAXINFOメッセージの処理で、lpmm->ptMinTrackSize.yへの値はもう少しシンプルに、GetSystemMetrics(SM_CYMINTRACK)で得た値にcyCharの値を加えてセットします。

C

1... 2 case WM_GETMINMAXINFO: 3 lpmm = (LPMINMAXINFO)lp; 4 // 旧コード lpmm->ptMinTrackSize.y = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) * 2 + cyChar; 5 lpmm->ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK) + cyChar; 6 return 0; 7...

そうすると意味的にも計算上も少し自然になるかと思います。

TextOut APIで文字列を描画したとき、クライアント領域のバックグラウンドの色によっては下記画像のようになって、少しおかしい(? 意図しないもの?)になっています。

イメージ説明

画像ではクライアント領域のバックグラウンド色をグレーにしてテキスト描画時に差が出るようにしています。これはWM_CREATEメッセージの処理中で得ている文字の高さでtmExternalLeadingの値を加算している為ですね。

リファレンスによると

TEXTMETRICA 構造体 (wingdi.h) - Microsoft Learn

tmExternalLeading

アプリケーションが行間に追加する追加の先頭 (スペース) の量。 この領域はフォントの外側であるため、マークが含まれていないため、OPAQUE モードまたは TRANSPARENT モードのテキス> ト出力呼び出しによって変更されません。 デザイナーでは、このメンバーを 0 に設定できます。

とのことなので、これを加算せず、単純にcyChar = tm.tmHeight; とすればフォントの高さそのままがウィンドウサイズ縮小の最低サイズになります。その方が或いは自然かもしれませんので、検討してみてください。

こちらでは質問者さんのコードをそのままに、Windows 10 Pro上で、Visual Studio 2022でビルドしたもので動作を確認しました。

投稿2025/01/05 05:55

dodox86

総合スコア9300

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mery

2025/01/05 07:20

回答ありがとうございます。コードを修正案の通りに変更し、文字の高さを求めるところもcyChar = tm.tmHeight;と変更したらうまくいきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.34%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問