ダイアログボックスでの画像処理ソフト開発におけるヒストグラム表示の問題と解決方法

このQ&Aのポイント
  • SDKを使用して画像処理ソフトを開発しているが、ダイアログボックスに入力した画像のヒストグラムを表示する際に問題が発生している。
  • ヒストグラムは単に白黒で表示させたいが、任意の図形の描画方法が不明。
  • コントロールの設定やデバイスコンテキストの取得方法についてアドバイスが欲しい。
回答を見る
  • ベストアンサー

ダイアログボックス・・・・・ bySDK

現在SDKにて画像処理ソフトを作成しています。もちろん個人にて。 そこで確実にほしい機能”ヒストグラム”の表示を行おうと思ったのですが、問題が起こりました。 目的は”2値化"という処理に伴い、ダイアログボックスに入力した画像のヒストグラムを表示させたいということです。 もちろんヒストグラムは単に白黒だけで表示させたいと思っています。 問題というのはダイアログボックスに任意の図形をどのように描画するかです。ビットマップの描画は以前行ったことがあるのですが、任意の図形は行ったことがありませんでした。 試しに、ダイアログボックスにPicture Controlを貼り付け、そのPicture ControlのデバイスコンテキストをGetDCにより無理やり取得し、そのデバイスコンテキストに直線などの描画を行ってみましたが、表示はされませんでした。(あたりまえかも・・・・) そこでまず、ダイアログボックスに使用するコントロール類は何を設定したらよいか? そして、そのコントロールから取得したデバイスコンテキストに直接描画は可能か? これらの質問に答えられる方はアドバイスをお願いしたいと思います。 よろしくお願いします。

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★最初に『点線』とはフォーカスを意味しています。 ・このフォーカスだけを上手く消す方法は簡単ではありません。  ボタンでも押されるとフォーカスが移り、点線が表示されます。これと同じ。  これを表示しないようにするには、やはりオーナードローでフォーカス時に  点線を描画しなければ良いことになります。でも、スライダーコントロールも  オーナードローするのは大変です。 ・そこで提案。  (1)スライダーコントロールをサブクラス化します。  (2)サブクラス化したコントロールの新しいプロシージャで WM_LBUTTONUP を処理します。  (3)処理内容は WM_LBUTTONUP の時、コントロールの ID を親のプロシージャへ発行します。  (4)発行は WM_COMMAND メッセージを使ってコントロールの ID を送ります。   PostMessage( hDlg, WM_COMMAND, MAKEWPARAM(nID,0), (LPARAM)hFocus );   hDlg⇒ダイアログのウインドウハンドル   hWnd⇒コントロールのウインドウハンドル   nID⇒コントロールのID(GetDlgCtrlID(hWnd) で取得可能)   hFocus⇒NULLか、ボタンなどの他のコントロールのウインドウハンドル  (5)親のダイアログ・プロシージャの WM_COMMAND でスライダーコントロールの ID は   SetFocus( NULL ); または SetFocus( (HWND)lParam ); とフォーカスを無くすように記述します。  ※これでスライダーコントロールをドラッグ移動後は、点線が表示されなくなります。   ただしドラッグ移動中は、どうしてもフォーカスを示す点線が表示されてしまいます。   コントロールの仕組み上、移動中の点線は描画されます。移動後にフォーカスを別の   コントロールに移すことで点線を残さないというアイディアです。 ・サブクラス化は、GetWindowLong、SetWindowLong、CallWindowProc 関数を利用します。  下の『参考URL』をどうぞ。 ・親のダイアログ・プロシージャの WM_COMMAND だけ載せます。  case WM_COMMAND:   switch ( LOWORD(wParam) ){    case IDC_BUTTON1: 他のボタン1の処理 break;    case IDC_BUTTON2: 他のボタン2の処理 break;     :    case IDC_SLIDER1:  break; ←特に処理しなくて良い。    case IDC_SLIDER2:  break;  理由:SetFocus( (HWND)lParam );を下でまとめて処理するから。    case IDC_SLIDER3:  break;    default:return FALSE;   }   SetFocus( (HWND)lParam );   break; ・上記の WM_COMMAND で IDC_SLIDER1 ~ IDC_SLIDER3 を追加します。  あとはサブクラス化したコントロールの新しいプロシージャ関数を作るだけです。  関数名は自由と思いますが、  元のプロシージャ名を DefSliderProc、  新しいプロシージャ名を NewSliderProc  などとしておくと分かりやすいかも。 ・以上。参考に!→上手くいかないときは次の回答でサンプルを載せます。

参考URL:
http://wisdom.sakura.ne.jp/system/winapi/win32/win64.html
noconan
質問者

お礼

長々と丁寧な解説ありがとうございました。 以前にサブクラス化を行ったことがあるので、この解説を参考に完成させることができると思います。 もし何か問題がありましたら、そのときはよろしくお願いします。

その他の回答 (2)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★追記。 ・http://www.kumei.ne.jp/c_lang/sdk/sdk_60.htm→『第60章 ステータスバーを作る その4』  こちらのリンクの方がオーナードローが分かりやすいかな。  その他、オーナードロー、WM_DRAWITEM メッセージや、DRAWITEMSTRUCT 構造体でネット検索すると  いろいろなサンプルが見つかります。 ・以上。 typedef struct tagDRAWITEMSTRUCT {  UINT CtlType;  UINT CtlID; ←コントロールのID(Picture ControlのID)  UINT itemID;  UINT itemAction;  UINT itemState;  HWND hwndItem;  HDC hDC; ←デバイスコンテキストのハンドル(描画時はこれを使う、GetDCしなくて良い)  RECT rcItem;  DWORD itemData; } DRAWITEMSTRUCT;

参考URL:
http://www.kumei.ne.jp/c_lang/sdk/sdk_60.htm
noconan
質問者

補足

返答ありがとうございました。 早速オーナードローでやってみたところ、作成することに成功しました。 ありがとうございました^^ ついでに1つ聴いてもよいでしょうか? ダイアログボックスにスライダーをつけているのですが、プログラムを実行しダイアログボックスを開き、スライダーを操作すると、スライダー自体が選択されたように点線で囲まれてしまいます。 実際これがなければいいのですが、どのように削除するかわかりません。 もしお知りになられるなら、削除する方法を教えていただきたいです。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★サブクラス化か、オーナードロー描画を行う。 ・コントロールには独自のプロシージャがあるためその関数ルーチンで WM_PAINT の  処理から毎回消されます。よって、無理やりデバイスコンテキストを取得して描画  しても駄目です。コントロール(Picture Control)をサブクラス化してその WM_PAINT  で描画するか、コントロール(Picture Control)をオーナードローに設定します。 ・オーナードローにするとオーナー(ダイアログ)のプロシージャで描画を記述できます。  この方法ならサブクラス化しないですむのでお勧めです。 ・オーナードローの場合は WM_DRAWITEM メッセージを処理します。  ここに描画を記述します。 ・下の『参考URL』をどうぞ。これはボタンですが他のコントロールも同じ考えです。  あとコントロール(Picture Control)にはオーナードロー描画のフラグをダイアログの  エディタでチェックしておくこと。 ・以上。参考に!

参考URL:
http://www.kumei.ne.jp/c_lang/sdk/sdk_41.htm

関連するQ&A

  • ダイアログボックスについて。

    ダイアログボックスについての質問です。 開発環境はVisual C++ 2005.netでありSDKを利用しています。 ダイアログボックスにPicture Controlを貼り付け、Combo Boxの内容が変わるたびにそのPicture Controlに画像を表示するようなプログラムを作りたいと考えています。 自分が考える手順としてはまずPicture Controlについてサブクラス化を行い、親のダイアログボックスが表示されると同時にPicture ControlのプロシージャでWM_CREATEメッセージを受け取り描画を行う。 そして親のダイアログボックスに貼り付けたCombo Boxの内容が変更された場合に、Picture ControlのウィンドウハンドルにむけてWM_PAINTメッセージを送信する。 こんな手順で行いたいのですが、少し不安な部分が出てきました。 Combo Boxの内容が変更され、Picture Controlのウィンドウハンドルに向けてWM_PAINTメッセージを送信し、Picture ControlプロシージャではWM_PAINTメッセージがきたとき画像の描画を行う場合、このプロシージャではどの画像を描画してよいか不明です。 そのため何番の画像の表示命令が来たのかを示すために、親のダイアログボックスに貼り付けたCombo Boxが変更された場合、Picture Controlに向けてWM_PAINTメッセージと表示画像番号をパラメータとして送信したいのです。 もちろんグローバル変数を用意すれば簡単なのですが、できるだけ使用しないように記述をしたいのです。そこで考えたのが、 SendMessage(GetDlgItem(hDlgWnd, IDC_PICTURE), WM_PAINT, 0, MAKELPARAM(0, number)); このようにnumberをLPARAMの下位ワードとして送信しようと考えました。 このメッセージ送信を行い、Picture ControlプロシージャでWM_PAINTメッセージが到着したとき、LOWORD(lparam)からnumberを取り出す。 実現したい目的のため、このような方法を考えましたが、エラーなく実行できるでしょうか? もしあやしい部分が見つかった場合はアドバイスをお願いします。そしてこの方法よりも簡単に処理できる方法があれば教えていただきたいです。 自分としてはサブクラス化は面倒なので、Picture Controlをオーナードローとして扱う方法も考えましたが、うまく動きませんでしたTT

  • VC++のダイアログボックスに絵を描くには?

    VC++初心者なんですが、画像処理関係のプログラムをVC++で作っています。で、子ウィンドウに表示されている画像のRGBそれぞれのヒストグラムをダイアログボックスに表示したいのですが、ダイアログボックスに絵(グラフ)を描く方法がわかりません。どういう手順でやればいいですか?エディットボックスにGDIとかで絵を描くことは可能なんですか?またはピクチャーボックスですか?

  • ピクチャーコントロールのデバイスコンテキストを取得するためには?

    VC2005についてです ピクチャーコントロールのデバイスコンテキストを取得するためには どうすればよいでしょうか? MDIGetActive()->GetDC()->TextOutA(20,50,"文字列です"); この様にすれば、アクティブになった 子ウィンドウデバイスコンテキストを取得することができますが、 アクティブになった、この子ウィンドウの上にある ピクチャーコントロールに 描画するためには どうすればよいでしょうか? MDIで、複数のウィンドウのうちで アクティブになった ものだけを 操作したいのです。 よろしくお願いします。

  • ダイアログボックスからビットマップを選択後画像を消去したい

    visualstadioでVC++を使って、ビットマップ表示をしたいのですが、ピクチャーコントロールにsetbitmapを使って描画したのはいいのですが、消去ができません。 ダイアログボックスから画像を選択して、画像パスをエディットコントロールに表示します。表示されたパスから画像を表示しています。エディットコントロールのパスを消去すると、画像も消去したいのですが、消去できません。ネットを調べてもでてきません。 お願いします。

  • ピクチャーコントロールのデバイスコンテキストを取得するためには?

    VC2005についてです ピクチャーコントロールのデバイスコンテキストを操作するためには どうすればよいでしょうか? void CMainFrame::OnButton() { // ここに処理を書く CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; CButton *pButton =  (CButton*)pFrame->m_wndDialogBar.GetDlgItem(IDC_BUTTON1); pButton->SetWindowText("button"); MDIGetActive()->GetDC()->TextOutA(0,0,"文字列です"); } この様にすれば、アクティブになった 子ウィンドウデバイスコンテキストを取得することができますが、 アクティブになった、この子ウィンドウの上にある ピクチャーコントロールに 描画するためには どうすればよいでしょうか? MDIで、複数のウィンドウのうちで アクティブになった ものだけを 操作したいのです。 MDIGetActive()->GetDlgItem(IDC_PICTURE1)->GetDC()->TextOutA(0,0,"文字列です"); この方法では、エラーがでます。 よろしくお願いします。

  • ピクチャーコントロールへの描画方法について

    お世話になります、fujitomoです。 現在、Visual Studio2005にてC++のダイアログベースのアプリケーションを作成しており、行き詰った箇所があったため質問させて頂きました。 アプリケーションの内容としては 現在、アプリケーションで、ダイアログベース上にピクチャーコントロールを2つ設置し、それぞれに波形を描画させています。 ピクチャーコントロールへの波形の描画にはメモリデバイスコンテキストを使い、それぞれ波形描画用のCStatic派生クラスを作成し、そのクラスを SubclassDlgItem でメインダイアダイアログのサブクラスとし、描画間隔として、それぞれの描画クラス内で SetTimer(1,10,NULL) でタイマーイベントを起こし、メモリデバイスコンテキストの描画更新をしています。 ここで質問させていただきたい事なのですが、 2つのピクチャーコントロールのうち、1つのピクチャーコントロールへのみ波形描画を実行させているときはピクチャーコントロールの端から端まで描画が約7秒かかるのに対し、 2つのピクチャーコントロールの描画を同時に実行させた場合には端から端までで約11秒もかかってしまいます。 これを何とか、1つのピクチャーコントロールへの描画時間と同じ時間まで早く出来ればなと思っているのですが、どの様に工夫すれば時間短縮をさせることが出来ますでしょうか? 2つのクラスでそれぞれ10msのタイマーを動かしているのが問題なのかと思い、メインダイアログで10msのタイマーイベントを発生させ、それぞれの描画クラスに描画更新のメッセージを送信させるようにコードを変更してみたのですが、やはり同じ結果となりました。 開発環境は Widows CE 6.0 Visual Studio 2005 です。 ご意見、ご回答をお待ちしております。よろしくお願い致します。

  • c言語を使いダイアログにbmpを表示したい 

    はじめまして、 私は、c言語は初心者なのでが、ダイアログボックスに、画像(bmp)が表示することができません。 ソースは、 hdc = BeginPaint(hDlg, &ps); //指定ウィンドウ内での描写準備 // ビットマップをファイルからロードする hBitmap = ::LoadBitmap( NULL, _T("test.bmp") ); // ウィンドウのデバイスコンテキストハンドルを取得する hDC = GetDC( hDlg ); // メモリデバイスコンテキストを作成する hCompatDC = CreateCompatibleDC( hDC ); // ロードしたビットマップを選択する GetObject(hBitmap, sizeof(BITMAP), &bmp); // ビットマップをウィンドウに転送する(表示する) if(hBitmap != NULL){ StretchBlt( hDC, 0, 0, 100, 100, hCompatDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY ); SendDlgItemMessage( hDlg, IDC_STATIC, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap); } なのですが、これはメインウィンドウでは動くのですが、ダイアログボックスでは動かずこまっています。 どうか、助言のほどよろしくお願いします。

  • MFC デバイスコンテキストについて

    MFCのデバイスコンテキストを取得して、DirectXなどで描画を行っています。 環境は、 VS2008 DirextX 9.0 MDIなんですがOnInitDialogでDirectXのデバイスを取得しています。 次にOnDrawで描画を行っています。 GetDcでコンテキストを取得し、円の描画を行っています。 MDIですので、5以上のファイルを作成すると、描画が行われなくなります。 共通デバイスコンテキストは、5以上持てないということは検索して分かったのですが、5以上のファイルに描画を成功させるためには、どうすればいいのでしょうか? ・単純に新規ファイルを作ったときに、以前に作ったファイルのデバイスコンテキストを開放また、Directxのデバイスを開放すればいい? ・DirectXのデバイスをファイルごとに作成するのではなく、共通してもてば解決できる?? ・そもそも解放したりしても無理?? と考えているのですが、どうでしょうか? 助言をお願いします。

  • ダイアログの表示と同時に、ピクチャーボックスを塗る方法

    あるサイトの過去ログで以下を見つけました。 エラーは出ませんが、何も起こりません。 このコードは何をしようとしているのでしょうか? ************************* ダイアログ上にピクチャーボックスを配置して、ダイアログの表示と同時に、ピクチャーボックスを塗る方法。 まず、ピクチャコントロールをClassWizardのメンバ変数タブによりm_pictureとして実態を作成します。 その後、 class CPictureDlg { private: CBitmap m_bitmap; // ... }; BOOL CPictureDlg::OnInitDialog() { CDialog::OnInitDialog(); // ... CDC desktopDC; desktopDC.Attach ( ::GetDC ( NULL ) ); CDC memDC; memDC.CreateCompatibleDC ( &desktopDC ); m_bitmap.CreateCompatibleBitmap ( &desktopDC, 100, 100 ); CBitmap *pOldBitmap = memDC.SelectObject ( &m_bitmap ); CRect rcPicture ( 0, 0, 100, 100 ); CBrush brush; brush.CreateStockObject ( WHITE_BRUSH ); memDC.FillRect ( &rcPicture, &brush ); memDC.SelectObject ( pOldBitmap ); m_picture.SetBitmap ( ( HBITMAP ) m_bitmap.GetSafeHandle () ); ReleaseDC ( &desktopDC ); memDC.DeleteDC (); }

  • カレンダーコントロールのダイアログボックス

    ACCESSでボタンをクリックすると、カレンダーコントロールのダイアログボックスが表示されて、日付が入力出来るようにしたいのですが... この方法で日付を入力するテキストボックスに共通で使用出来たらと考えています。 カレンダーコントロールのダイアログボックスの作成から分からないのでお願いします。

専門家に質問してみよう