• ベストアンサー

猫でも 20章

LRESULTはlong型、DWORDはmsdnより、「32 ビットの符号なし整数、またはセグメント アドレスとそれに関連するオフセット」、SendMessageは返り値はLRESULT型。それで、猫でもわかるプログラミング20章(http://www.kumei.ne.jp/c_lang/sdk/sdk_20.htm)、の上のほうにリスト等の情報を取得するのに、 int getDlg(HWND hDlgWnd) { GetWindowText(GetDlgItem(hDlgWnd, IDC_EDIT1), edit_str, sizeof(edit_str)); ScrPos = GetScrollPos(GetDlgItem(hDlgWnd, IDC_SCROLL1), SB_CTL); ListNo = (int)(DWORD)SendMessage(GetDlgItem(hDlgWnd, IDC_LIST1), LB_GETCURSEL, 0L, 0L); ComboNo = (int)(DWORD)SendMessage(GetDlgItem(hDlgWnd, IDC_COMBO1), CB_GETCURSEL, 0L, 0L); return 0; } とあるのですが、SendMessageを(int)(DWORD)とキャストしているのはなぜなんでしょうか。(int)ではダメですか?

  • arcsin
  • お礼率46% (194/417)

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

  • ベストアンサー
  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.2

 プログラムそのものが、コンパイラ依存に見えてしょうがあません。  intの大きさに関しては、Cの規約によれば、定義されていません。型の大きさが、short <= int <= long を満たしていれば、 後は、コンパイラーの作者がコンパイラーを作りやすいように勝手に決めて良いことになってます。(本来は、もう少し条件がありますが)  というわけで、intの変数に32ビットの符号無し整数が格納できるかどうかは、その時に使用するコンパイラー次第と言うことになります。  普通は、32ビットのCPUを使用したときには、32ビットの数値が一番使いやすいので、最近のwindows環境では、intは32ビットの符号付き整数となることが多いと思いますので、多分、そのプログラム符号のせいで少々面倒なことになるかも・・・ですね。(たとえば、ListNoの大小を比較は単純にはできません。)  せめて、(unsigned int)ならば、まだ動く確率は大きいですが・・・それでも、まだコンパイラ依存です。  この教訓は・・・windows APIとのやりとりを行う変数は、極力、SDKで定義されたtypedefを使用することです。外部とのやりとりのため、どうしようもないときだけ、DWORDだとunsigned longに変換。数値の大きさが絶対に保証できるときに限り、コンパイラ依存を覚悟でそれ以下の大きさの型にする・・・でしょうか。  intやlongの大きさが絡む問題は、注意が必要です。

arcsin
質問者

お礼

経験も浅いため、少し私には理解するのに時間がかかりそうですが、また後ほど読み返してみたいと思います。詳しく考察していただき、ありがとうございます。

その他の回答 (1)

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

なぜでしょうね? intでキャストして問題ないはずですけど。 というか、ListNoとComboNo、本来はlongであるべきなんですけど・・・ あくまでサンプルということで、すべて鵜呑みにするのは良くないということですね。

arcsin
質問者

お礼

そうなんですか~。 少し安心しました。ありがとうございます

関連するQ&A

  • 1と表示させたいが12と表示される

    windows XP VC++.net 2003です。 よろしくお願いします。 症状は毎回コピーアンドペーストでプログラムを書くよりも 関数化してソースをきれいにしようと思い BOOL ButtonNumber (int bNumber,HWND hWnd) { long z; char sBuff[100]; char number[100]; wsprintf(number,"%d",bNumber); z = GetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff,99); if(z == 0){ SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),number); return TRUE; } if(z == 10){ //桁数が多すぎる警告メッセージ MessageBox(NULL,"桁数が多すぎます。","警告",MB_OK); return TRUE; } z = atol(sBuff); wsprintf(sBuff,"%d1",z); SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff); return TRUE; } という関数を作りました。 numberに1という数字が入っていてエディットボックスに1と表示されるはずなのですが12と表示されてしまいます。 ためしにnumberに12と入れてみると表示されるのが122 123と入力すると1232と表示されてしまいます。 SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),number); どこも間違っていないように思いますが・・なんででしょう・・ 関数化せずmainに直接書き込んでいけば正常に1と表示されます・ switch (LOWORD(wParam)) { case IDC_BUTTON1: ButtonNumber(1,hWnd); case IDC_BUTTON2: a = GetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff,99); if(a == 0){ SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),"2"); return TRUE; } if(a == 10){ //桁数が多すぎる警告メッセージ MessageBox(NULL,"桁数が多すぎます。","警告",MB_OK); return TRUE; } a = atol(sBuff); wsprintf(sBuff,"%d2",a); SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff); return TRUE; この場合BUTTON1は12と意図しない表示をしますが BUTTON2はちゃんと2と表示されます。 非常に困っていますよろしくお願いします。

  • MFCのエディットボックスの値をスピンボタン

    エディットボックスの値をスピンボタンの初期値にしたく、 下記コーディングにしたのですが CString Item; m_Spin->SetPos(((CEdit*)GetDlgItem(IDC_EDIT1))->GetWindowText(Item)); SetPos' : 1 番目の引数を 'void' から 'int' に変換できません。 とのエラーになります。 どのように変更したらよいかお教えください。

  • 初回のスピンボタンの挙動

    下記コードを記入し、スピンボタンの増加をクリックすると 最初の一回目に触った時のみ値がマイナスされる現象がでます。 なぜでしょうか? 1)INIファイルから値を読み込みエデットボックスに表示する。 2)スピンボタンの増加をクリックすると、最初の一回目に触った時のみ値がマイナスされる (エデットボックスの値が50だとすると49になる) 3)再度INIファイルから値を読み込みエデットボックスに表示する。 4)二回目からマイナスされない。 (エデットボックスの値が50だとすると51になる) スピンボタンのOnDeltapos UDACCEL stUD; stUD.nSec = 1; stUD.nInc = 1; // ここで変化量設定 CSpinButtonCtrl* m_Spin=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN1); m_Spin->SetRange32(0,300); //レンジ CString str; ((CEdit*)GetDlgItem(IDC_EDIT1))->GetWindowText(str);//エディットから文字列を int a=atoi(str);//文字列を数字に変換 m_Spin->SetPos(a); //初期値 m_Spin->SetAccel(1,&stUD);//変化量 m_Spin->SetBuddy((CSpinButtonCtrl*)GetDlgItem(IDC_EDIT1));//エディットに関連付け 環境 Windwos XP,Microsoft Visual C++ 6.0

  • VC++におけるCStringの変換

     VisualC++6.0において、CStringというオブジェクトがありますよね。  たとえば、Edit->GetWindowText(str);  などで、strにEditのさす文字列を入れたりして、そのあとにstrを使って算術演算をするときにどうしてもstrをintかlong型に直したいのです。  キャストの仕方がよくわからないので、知っている方教えてください。よろしくお願いします。

  • LineTo,MoveToについて

    MFCのダイアログベースで 変化を表すグラフを作成したのですが 線を描くときに原点復帰してしまいます。 左上のエディットに数値をいれ 実行を押すと座標(200,200)から横にエディットで入力した数値分線を引いていくというものです。 Timerを使い1秒ごとに書かせています。 void CsinDlg::OnTimer(UINT_PTR nIDEvent) { // TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。 static int count=0; static double i,x=0; char buf[100]; CString str; /*------描写設定----*/ CWnd* h = GetDlgItem(IDC_BB); CDC* pDC=h->GetDC(); //-----------------------------------// CEdit *edit = (CEdit*)GetDlgItem(IDC_EDIT1); edit->GetWindowText(str); i = atof((const char*)str); x=x+i; sprintf(buf,"%lf",x); siki_edit.SetWindowText(buf); /*---------------------------------------*/ if(count==0) pDC->MoveTo(200,200); // 座標(200,200) に移動 pDC->LineTo(200+x,200); // 座標(200+x,200) まで線を引く count++; h->ReleaseDC(pDC); CDialogEx::OnTimer(nIDEvent); } 実行結果は添付した画像のようになります。 イメージではcountが0の時だけMoveToで動かし、それ以降は座標(200,200)から横に線を引いていきたいのですが。 どのように直せばよいのでしょうか? LineToからLineToの指令ができないということでしょうか?

  • 解像度が変わるとEditコントロールの位置がずれる

    いつも皆様、お世話になっております。 一つ教えてください。 解像度が変わるとエディット・コントロールの位置がずれるのですが、 ずばりクリックした行にエディット・コントロールを張り付かせたいです。 EditCellShow 関数は、セルを↑↓←→で移動した場合 や リストコントロールをスクロールした時などに呼び出されます。 (最後にクリックした行、列は、正しく拾えているものとします。) (そして、workRow、workColumnに代入されます。) 例えば、1280 × 800 ピクセル (Windows Vista 32bit)では、以下のコードで正常に動作します。 1920 × 1080 ピクセル (Windows7 64bit)では、上にずれます。 もし解像度の問題でなければすみません、でも他のXPマシンや Windows7 マシンでも正常に動作しました。 void CFileListCreatorDlg::EditCellShow(int workRow,int workColumn) {   if (m_xvChkEditCellMode == TRUE){     CFileListCreatorDlg::StatusStringSet(_T("ファイル名 や 備考欄 の 編集モードになりました (セルをクリックするか、クリック後 矢印キーで素早く移動、Enterで確定)"),0,FALSE);     //StatusStringSet()関数は、ステータス文字を画面上部に表示し、警告音を鳴らすユーザー関数   }   ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT_Item),SW_HIDE);   ::ShowWindow(::GetDlgItem(m_hWnd,IDC_STATIC_Arrow),SW_HIDE);//追加2011.10.08   ::SetWindowText(::GetDlgItem(m_hWnd,IDC_EDIT_Item),_T(""));   //m_xcListは、IDC_LISTの変数名   m_xcList.SetItemState(workRow, // フォーカス&非選択状態にしたいアイテムのインデックス   !LVIS_FOCUSED | !LVIS_SELECTED, // 状態   LVIS_FOCUSED | LVIS_SELECTED); // マスク   //UpdateWindow(); HWND hWnd1 = ::GetDlgItem (m_hWnd,IDC_LIST); RECT rect;   int nItem;   int nSubItem;   //何回も代入していますが、特に意味はありません、参考サイトのまま ソースコードを使いたかったので、それに合わせました。 nItem = workRow; nSubItem = workColumn;   LastSelectedRow = nItem;   LastSelectedColumn = nSubItem;   ////0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報   if((nSubItem == 0 || nSubItem == -1 || nItem == -1) || (nSubItem != 3 && nSubItem != 8)){ //2011.09.22変更     //ファイル名と備考欄のみ編集可能に、他のカラムがクリックされた場合は、ファイル名編集欄に移動     nSubItem = 3;     LastSelectedColumn = nSubItem;   }   CFileListCreatorDlg::m_xcList.EnsureVisible(nItem, FALSE);   CString str = m_xcList.GetItemText(nItem,nSubItem);   ListView_GetSubItemRect(hWnd1,nItem,nSubItem,LVIR_BOUNDS,&rect);   if(nItem != -1)     ::SetWindowPos(::GetDlgItem(m_hWnd,IDC_EDIT_Item),     HWND_TOP,rect.left + (18),rect.top + 4 + ( 16*5+2 ), //追加2011.09.22 //(18)と( 16*5+2 )は、帳尻あわせ //HWND_TOPは、IDC_LISTのTOPを取っているのか? rect.right-rect.left - 3, rect.bottom-rect.top -1,NULL);   ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT_Item),SW_SHOW);   ::SetFocus(::GetDlgItem(m_hWnd,IDC_EDIT_Item));   ::SetWindowText(::GetDlgItem(m_hWnd,IDC_EDIT_Item),str);   ::SetWindowPos(::GetDlgItem(m_hWnd,IDC_STATIC_Arrow),//追加2011.10.08     HWND_TOP,rect.left + (18) -17 ,rect.top + 4 + ( 16*5+2 ), //追加2011.09.22 //(18)と( 16*5+2 )は、帳尻あわせ //HWND_TOPは、IDC_LISTのTOPを取っているのか? 17, 12 ,NULL);   ::ShowWindow(::GetDlgItem(m_hWnd,IDC_STATIC_Arrow),SW_SHOW);//追加2011.10.08 } 参考サイト: http://www.codeproject.com/KB/list/editing_subitems_in_listcontrol.aspx?display=Print (主に、項番10を参考にしました。) 画像を初めて添付しますが、文字が小さいなどの不具合があったら、すみません。 (画像は帳尻あわせをして、正常に動いている時のものです。)

  • エディットボックスでテキストの最後に入力したい?

    エディットボックスで最後の位置に ( が入力されたときに閉じ括弧の ) を出力して () としたいのです が、下のコードだと ( が入ったときに )( となってしまいます。いろいろ試していますが () と出力 できないので、わかる方よろしくお願いします。 int nStartChar, nEndChar; CEdit *edit1 = (CEdit *) GetDlgItem(IDC_EDIT1); if(pMsg->message == WM_CHAR) if(pMsg->wParam == '(') { edit1->GetSel(nStartChar, nEndChar); edit1->SetSel(nStartChar, nEndChar); edit1->ReplaceSel(")"); }

  • キャレットの現在位置の表示 (Win32API)

     Win32APIの習作としてエディタを作っているのですが, ステータスバーに現在のキャレット位置を表示する部分で困っています. いろいろ調べて下記のコードを書いてみたのですが, エディットコントロールに更新が無いとき(矢印キーで移動など) にキャレット位置の更新ができないです. 良い方法がありましたらご教授下さい. (ここのサンプルコードが良いとかでもありましたらお願いします.) //////////////////////////////////////////////////////////////// // MyEditor.c static const int FONT_WIDTH = 6; static const int FONT_HEIGHT = 18; int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { ...略... } LRESULT __stdcall WndProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp) { ...略... switch (uMsg) { ...略... case IDC_EDIT:{ char str[64]; POINT pt = {0, 0}; RECT rc = {0, 0, 0, 0}; GetCaretPos(&pt); wsprintf(str, "現在のキャレット位置 (%d, %d)", pt.x / FONT_WIDTH, pt.y / FONT_HEIGHT); SendMessage(hStatusbar, SB_SETTEXT, 1, (LPARAM)str); GetClientRect(hStatusbar,&rc); InvalidateRect(hStatusbar, &rc, TRUE); break ;} ...略... } return 0L; }

  • DlgDirSelectComboBoxEx

    VC++2010 でMFCアプリケーションを作成しているのですが、 DlgDirListComboBox関数によって一覧が表示されているコンボボックスから、 現在選択されている項目(ディレクトリ名、ドライブ名)を取得する処理で、 DlgDirSelectComboBoxExを使用するとアプリケーションが強制終了してしまいます。 何が悪いのかが解らず困っています。 詳しい方がいましたらご教授お願いします。 以下は私が作成したサンプルコードとなります。 BOOL CComboBoxTestDlg::OnInitDialog() { CDialogEx::OnInitDialog(); CString work; work = L"C:\\*.*"; DlgDirListComboBox( work.GetBuffer(), IDC_COMBO1, 0, DDL_DIRECTORY | DDL_DRIVES | DDL_EXCLUSIVE); m_ComboBox.SetWindowText(L"C:\\"); } void CComboBoxTestDlg::OnCbnSelchangeCombo1() { wchar_t str[1024]; memset(str, 0x00, sizeof(str)); DlgDirSelectComboBoxExW( this->m_hWnd, (LPTSTR)str, 1024, IDC_COMBO1); AfxMessageBox(str); }

  • コンボボックス表示文字列を取得する場合

    VC++ver6.0を使用しています。 コンボボックスのドロップダウンリストより 表示されている文字列を取得しようと思い、 下記のようにコーディングを行いました。 コンボボックスメンバ変数名:m_combo_year ON_CBN_SELCHANGE(IDC_COMBO_HYOJI_SEIREKI, OnSelChangeComboHyojiSeireki) void CKoyomiDlg::OnSelChangeComboHyojiSeireki() {  CString strComboYear;  m_combo_year.GetWindowText(strComboYear); } 実行すると、 ドロップダウンリストを 初期値2007 → 2006選択 → 2005選択 と、2回選択した場合 取得する値は 起動せず → 2007 → 2006 と、「選択した値」ではなく「表示していた値」を取得してしまいます。 何か解決策はございますでしょうか。 宜しくお願い致します。