ボタンが見えない?ボタンを大きく中央に表示する方法とは?

このQ&Aのポイント
  • ボタンを大きく中央に表示するプログラムを作りましたが、最初からボタンが現れません。どうしたら最初からボタンが現れるのでしょうか?
  • フォントをクリエイトし続けてリソースは尽きないのでしょうか?
  • ボタンの幅と高さ、親ウィンドウの幅と高さを表示するプログラム
回答を見る
  • ベストアンサー

最初ボタンが見えない

ボタンを大きく中央に表示するプログラムを作りました。 しかし中央をクリックするまでボタンが現れません。 どうしたら最初からボタンが現れるのでしょうか? またフォントをクリエイトし続けてリソースは尽きないのでしょうか? #include <windows.h> #include <stdio.h> HWND hB; LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP) { RECT rt; char s[99]; int W,H; static HFONT hF; switch(wM) { case WM_PAINT: GetClientRect(hW,&rt); W=rt.right-rt.left;H=rt.bottom-rt.top; DeleteObject(hF); hF=CreateFont(H/4,W/4,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,OUT_TT_ONLY_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,"MS Pゴシック"); SendMessage(hB,WM_SETFONT,(WPARAM)hF,1); MoveWindow(hB,W/4,H/4,W/2,H/2,1); sprintf(s,"幅=%d,高さ=%d",H,W);SetWindowText(hW,s); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: return(DefWindowProc(hW,wM,wP,lP)); } } WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int) { WNDCLASS wc; --略--(ここにウィンドウクラスwcをクラス名"I"で登録) RegisterClass(&wc); hW=CreateWindow("I","ボタンの親",WS_OVERLAPPEDWINDOW,0,0,0,0,0,0,hI,0); hB=CreateWindow("BUTTON","子",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,0,0,0,0,hW,0,hI,0); ShowWindow(hW,SW_SHOWMAXIMIZED); UpdateWindow(hW); while(GetMessage(&ms,0,0,0)) { TranslateMessage(&ms); DispatchMessage(&ms); } return (ms.wParam); }

  • keyguy
  • お礼率68% (895/1314)

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

>フォントをクリエイトし続けてリソースは尽きないのでしょうか? 正しく削除できていれば平気です。 1.WM_PAINTの処理がおかしい 自分でメッセージを処理するのであれば、BeginPaint()、EndPaint()は必須です。 2.WM_PAINTでやるべき処理ではない 親ウィンドウのサイズが変更されたらフォントを変えるのであれば、WM_SIZEでかまわないのでは? 3.DeletObjectする順番が違う。 WM_SETFONTでボタンのフォントを変更してから削除しましょう。 一番大きな原因は、おそらく1でしょう

keyguy
質問者

お礼

1,2.WM_SIZEでやるとタイムラグが有り1テンポ遅れて文字サイズが変わると思って渋っていたのですが実際にやってみるとうまくいきました。 3.デリートする順番ですが以前指摘を受けたようにフォントをクリエイトしてセンドした後デリートすると文字が大きくならない(多分瞬間的にだけ大きくなっている)のです。 だからフォントをクリエイトする直前まで以前のフォントをデリートしてはいけないのです。 とにかく以下のコーディングでうまくいきました。 ありがとうございました。 LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP) { RECT rt; int W,H; static HFONT hF; switch(wM) { case WM_COMMAND: SetFocus(hW);return 0; case WM_SIZE: GetClientRect(hW,&rt); W=rt.right-rt.left;H=rt.bottom-rt.top; if(hF!=0)DeleteObject(hF); hF=CreateFont(H/4,W/4,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,OUT_TT_ONLY_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,"MS Pゴシック"); SendMessage(hB,WM_SETFONT,(WPARAM)hF,1); MoveWindow(hB,W/4,H/4,W/2,H/2,1); return 0; case WM_DESTROY: DeleteObject(hF); PostQuitMessage(0); return 0; default: return(DefWindowProc(hW,wM,wP,lP)); } } WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int) { WNDCLASS wc; HWND hW; MSG ms; wc.lpszClassName ="I"; wc.lpfnWndProc =(WNDPROC)WinProcedure; wc.hInstance =hI; wc.style =CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; wc.cbClsExtra =0; wc.cbWndExtra =0; wc.hIcon =0; wc.hCursor =LoadCursor(0,IDC_ARROW); wc.hbrBackground =HBRUSH(COLOR_WINDOW+1); wc.lpszMenuName =0; RegisterClass(&wc); hW=CreateWindow("I","親",WS_OVERLAPPEDWINDOW,0,0,99,99,0,0,hI,0); hB=CreateWindow("BUTTON","子",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,0,0,0,0,hW,0,hI,0); ShowWindow(hW,SW_SHOW); UpdateWindow(hW); while(GetMessage(&ms,0,0,0)) { TranslateMessage(&ms); DispatchMessage(&ms); } return (ms.wParam); }

関連するQ&A

  • リストコントロールの文字の大きさ

    ハンドルがhWの主ウィンドウに hL=CreateWindow("LISTBOX",NULL,WS_CHILD|WS_VISIBLE,0,0,600,400,hW,HMENU(IDL),hI,0); でハンドルがhLのリストを配置して hF=CreateFont(36,(16,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,"MS Pゴシック"); SendMessage(hL,WM_SETFONT,(WPARAM)hF,1); として文字の大きさを2倍にしようとしたのですが リストコントロールは2倍になったと思って項目の間隔を文字が2倍であるかのように開くのですが肝心の文字が大きくなりません。 何が問題なのでしょうか?

  • void main(void){...}だとDosWindowが開くので

    わざわざWindowsアプリにして以下のようにするしかないのでしょうか? LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP) { //ここに宣言を置く switch(wM) { case WM_CREATE: //ここに処理を置く return 0; default: return(DefWindowProc(hW,wM,wP,lP)); } } WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS) { WNDCLASS wc; HWND hW,hPW; MSG ms; wc.lpszClassName ="goo"; wc.lpfnWndProc =(WNDPROC)WinProcedure; wc.hInstance =hI; wc.style =CS_HREDRAW|CS_VREDRAW; wc.cbClsExtra =NULL; wc.cbWndExtra =NULL; wc.hIcon =LoadIcon(NULL,IDI_EXCLAMATION); wc.hCursor =LoadCursor(NULL,IDC_ARROW); wc.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName =NULL; RegisterClass(&wc); hW=CreateWindow ( "goo", "教えて!goo", WS_OVERLAPPED, 0, 0, 640, 456, NULL, NULL, hI, NULL ); ShowWindow(hW,nCS); UpdateWindow(hW); while(GetMessage(&ms,NULL,NULL,NULL)) { TranslateMessage(&ms); DispatchMessage(&ms); } return (ms.wParam); } もっと簡単にDosWindowが開かないようにする方法はないのでしょうか? もしないとすると上記記述でもっと簡単にできないでしょうか?

  • 5^3をAPIで表示するために

    HDC hD; PAINTSTRUCT ps; TEXTMETRIC tm; HDROP hDrop; HFONT hPF,hF; string str; int i_w,i_h; ................................................................ case WM_PAINT: hD=BeginPaint(hW,&ps); SelectObject(hD,GetStockObject(OEM_FIXED_FONT)); GetTextMetrics(hD,&tm); i_w=tm.tmAveCharWidth; i_h=tm.tmHeight; SetTextAlign(hD,TA_LEFT|TA_TOP); ///////////////////////////////////////////////// str="5"; TextOut(hD,0,0,str.c_str(),str.size()); ///////////////////////////////////////////////// hF=CreateFont (i_h/2,i_w/2,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,OUT_DEFAULT_PRECIS ,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,"System"); hPF=(HFONT)SelectObject(hD,hF); ///////////////////////////////////////////////// str="3"; TextOut(hD,i_w,0,str.c_str(),str.size()); ///////////////////////////////////////////////// SelectObject(hD,hPF); DeleteObject(hF); EndPaint(hW,&ps); return 0; とすればできますがCreateFontによる文字サイズは思うようなサイズにならないことが多くてやってみないとサイズが半分になっているかどうかわかりません 酷い場合には半分のサイズを指定しても全くサイズが変わらない場合もあります 上の例では i_h=18でありi_w=8でありCreateFont後 キャラクタの高さはi_h/2=9となりキャラクタの幅はi_w/2=4になってくれました しかしこの場合はたまたまうまくいったので通常はこうはなりません 確実にもとのサイズの半分(面積比1/4)のキャラクタサイズにする方法を教えてください

  • 再起動したとき前起動分を強制終了するには?

    WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS) { WNDCLASS wc; HWND hW; MSG ms; wc.lpszClassName ="goo"; wc.lpfnWndProc =(WNDPROC)WinProcedure; wc.hInstance =hI; wc.style =CS_HREDRAW|CS_VREDRAW; wc.cbClsExtra =NULL; wc.cbWndExtra =NULL; wc.hIcon =LoadIcon(NULL,IDI_EXCLAMATION); wc.hCursor =LoadCursor(NULL,IDC_ARROW); wc.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName =NULL; RegisterClass(&wc); hW=CreateWindow ( "goo", "教えてgoo", WS_OVERLAPPED|WS_CAPTION|WS_THICKFRAME |WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU, 0, 0, 640, 480, NULL, NULL, hI, NULL ); ShowWindow(hW,nCS); UpdateWindow(hW); while(GetMessage(&ms,NULL,NULL,NULL)) { TranslateMessage(&ms); DispatchMessage(&ms); } return (ms.wParam); } のプログラムが2回目に起動したとき1回目の起動を強制終了するにはどうしたらいいのでしょうか?

  • プログラムを終わらせてください。

    下のプログラムが終わらなくて困っています。 終わらせる方法を教えてください。 #include <windows.h> #pragma argsused HWND hWmain; DWORD WINAPI Th(LPVOID) { char s[99]; for(unsigned i=0;i<4294967295;i++) SetWindowText(hWmain,itoa(i++,s,10)); return 0; } LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP) { static HANDLE hTh; DWORD thId; DWORD ExitCode; switch(wM) { case WM_CREATE: hTh=CreateThread(0,0,Th,0,0,&thId); return 0; case WM_DESTROY: GetExitCodeThread(hTh,&ExitCode); ExitThread(ExitCode); if(hTh!=0)CloseHandle(hTh); PostQuitMessage(0); return 0; default: return(DefWindowProc(hW,wM,wP,lP)); } } WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int) { WNDCLASS wc; MSG ms; wc.lpszClassName ="Q"; wc.lpfnWndProc =(WNDPROC)WinProcedure; wc.hInstance =hI; wc.style =CS_HREDRAW|CS_VREDRAW; wc.cbClsExtra =0; wc.cbWndExtra =0; wc.hIcon =LoadIcon(hI,0); wc.hCursor =LoadCursor(0,IDC_ARROW); wc.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName =0; RegisterClass(&wc); hWmain=CreateWindow("Q","",WS_OVERLAPPEDWINDOW,0,0,99,99,0,0,hI,0); ShowWindow(hWmain,SW_SHOW); UpdateWindow(hWmain); while(GetMessage(&ms,0,0,0)) { TranslateMessage(&ms); DispatchMessage(&ms); } return (ms.wParam); }

  • 再起動時、前起動分のハンドルを得る方法は?

    WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS) { WNDCLASS wc; HWND hW; MSG ms; //ここで前起動クローンのアプリやWindowのハンドルを取得したい wc.lpszClassName ="goo"; wc.lpfnWndProc =(WNDPROC)WinProcedure; wc.hInstance =hI; wc.style =CS_HREDRAW|CS_VREDRAW; wc.cbClsExtra =NULL; wc.cbWndExtra =NULL; wc.hIcon =LoadIcon(NULL,IDI_EXCLAMATION); wc.hCursor =LoadCursor(NULL,IDC_ARROW); wc.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName =NULL; RegisterClass(&wc); hW=CreateWindow ( "goo", "教えてgoo!", WS_OVERLAPPED|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU, 0, 0, 640, 456, NULL, NULL, hI, NULL ); ShowWindow(hW,nCS); UpdateWindow(hW); while(GetMessage(&ms,NULL,NULL,NULL)) { TranslateMessage(&ms); DispatchMessage(&ms); } return (ms.wParam); } 上記アプリで//行で前起動時のWindowのハンドルを得るにはどうしたらいいのでしょうか?

  • 2重起動を防ぐために

    WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int) { WNDCLASS wc; HWND hW; MSG ms; HANDLE hMutex; hMutex=CreateMutex(NULL,TRUE,"UniqueName"); if(!hMutex)return FALSE; if (GetLastError()==ERROR_ALREADY_EXISTS)return FALSE; とすればよいいうサイトがあります。 こうした後、最終的にこのアプリを終了するときMutexを閉じる必要はあるのでしょうか。 アプリの終了で自動的に閉じられるから何もしなくてよいのでしょうか教えてください。

  • WM_QUERYENDSESSIONを使って次文で

    #include <windows.h> LRESULT CALLBACK WndProc(HWND hW,UINT ms,WPARAM wp,LPARAM lp) { HDC hD; PAINTSTRUCT ps; static int width=0,height=0; static TCHAR strSize[128]; static boolean b_logoff; int i; switch(ms) { case WM_QUERYENDSESSION: b_logoff=true; i=MessageBox(hW,"end?","?",MB_YESNO|MB_TOPMOST); if(i==IDNO)b_logoff=false; case WM_CLOSE: case WM_DESTROY: PostQuitMessage(0); return b_logoff; case WM_SIZE: width=LOWORD(lp); height=HIWORD(lp); return b_logoff; case WM_PAINT: hD=BeginPaint(hW,&ps); wsprintf(strSize,"width = %d : height= %d",width,height); TextOut(hD,10,10,strSize,lstrlen(strSize)); EndPaint(hW,&ps); return b_logoff; } return DefWindowProc(hW,ms,wp,lp); } ユーザがWindowsを終了させようとしたときに ウォーンング用の警告ボックスを表示したのですが Noボタンを押してもWindowsが終了してしまいます 何が悪いのでしょうか?

  • 2重軌道防止のサイトの説明

    に従って以下のようにしましたが 2重起動を発見してやめるために return false; としていますが return true; としたり booleanをやめて return int(0) とするとどうなるのでしょうか? WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int) { WNDCLASS wc; HWND hW,hPW; MSG ms; unsigned pos; HANDLE hMutex; hPW=FindWindow("goo","I am good."); hMutex=CreateMutex(NULL,TRUE,"UniqueName"); if(!hMutex)return FALSE; if (GetLastError()==ERROR_ALREADY_EXISTS) { ShowWindow(hPW,SW_RESTORE); SetForegroundWindow(hPW); return FALSE; } ・・・・・・・・・・・・・・・・・・・・

  • ダイアログボックスのボタンコントロールのフォーカスについて

    ダイアログボックスのボタンコントロールのフォーカスについて 教えて下さい。  モーダルダイアログにボタン「OK」を一つ貼り付けて それを「標準のボタン」(BS_DEFPUSHBUTTON)として作成したのですが ダイアログ表示直後は下画像(1)のようになってエンターキーを押しても 反応しません。何度かカーソルキーを押すとようやく(2)のように ボタンに枠線がついてエンターで押せるようになるのですが ダイアログ表示直後に(2)のようにするにはどうするべきでしょうか? ダイアログのコールバック・プロシージャ(WM_INITDIALOG部分でボタン作成) LRESULT CALLBACK SettingWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ switch (msg){ case WM_INITDIALOG: CreateWindowEx(0x00000000,"BUTTON","OK", WS_CHILD |WS_VISIBLE| WS_TABSTOP | BS_DEFPUSHBUTTON, 16,16,80,21,hWnd,(HMENU)IDOK,GetModuleHandle(0),0); return TRUE; } return FALSE; }

専門家に質問してみよう