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

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

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

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

Win32 API

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

解決済

WinAPI 文字列に関して

BeatStar
BeatStar

総合スコア3

C

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

Win32 API

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

2回答

0評価

0クリップ

1411閲覧

投稿2016/11/08 02:06

C/C++ ( WindowsAPI実装 ) でやっています。

WindowsAPI で GetOpenFileName関数を使って "ファイルを開く" ダイアログを表示しようとしています。

一応最低限のものはできたのですが、フィルタが思ったように動きません。

C++

ofn\.lpstrFilter = TEXT\("画像ファイル \(\*\.gif, \*\.jpg, \*\.jpeg, \*\.png, \*\.bmp\)\\0\*\.gif;\*\.jpg;\*\.jpeg;\*\.png;\*\.bmp\\0"\) TEXT\("動画ファイル \(\*\.mp4, \*\.flv, \*\.avi, \*\.wmv, \*\.mkv\)\\0\*\.mp4;\*\.flv;\*\.avi;\*\.wmv;\*\.mkv\\0"\) TEXT\("音声ファイル \(\*\.mp3, \*\.wav, \*\.3gp, \*\.3g2\)\\0\*\.mp3;\*\.wav;\*\.3gp;\*\.3g2\\0"\) TEXT\("テキストファイル \(\*\.txt, \*\.data, \*\.data\)\\0\*\.txt;\*\.dat;\*\.data\\0"\) TEXT\("C/C\+\+ \(\*\.c, \*\.cc, \*\.cpp, \*\.h, \*\.hpp, \*\.lib, \*\.o, \*\.obj, \*\.dll, \*\.exe, \*\.rc, \*\.res\)\\0\*\.c;\*\.cc;\*\.cpp;\*\.h;\*\.hpp;\*\.lib;\*\.o;\*\.obj;\*\.dll;\*\.exe;\*\.rc\*\.res\\0"\) TEXT\("Java \(\*\.java, \*\.class, \*\.jar, \*\.manifest\)\\0\*\.java;\*\.class;\*\.jar;\*\.manifest\\0"\) \.\.\.\.;

のように直接渡すなら普通にうまくいくのですが、

汎用化するにはよくないと思っています。

( リスト部分が縦に長ったらしくなるため。 )

これをビット演算によって分岐させようと考えています。

ビット演算は「ロベールのC++教室」の「ビットでフラグ」にある

C

#define BIT\(n\) \(\(unsigned int\)1 << \(num\)\)

を埋め込み、

JPG_TYPE を BIT(1), PNG_TYPE を BIT(2) ... のように定義し、

C++

// 引数 DWORD flag に ビットが詰まっているとする if\( flag & JPG_TYPE \){ // ここで "JPG \[ \*\.jpg, \*\.jpeg \]\\0\*\.jpg;\*\.jpeg\\0" を追加 }else if\(\.\.\.\){ }

のようにしました。

C由来の char型だと追加が面倒なので C++ の std::string を使い、

C++

string filter; filter \+= string\( "JPG \[ \*\.jpg, \*\.jpeg \]\\0\*\.jpg;\*\.jpeg\\0" \);

という感じで 追加します。

動くかどうかわからないので、ビット演算関連は省いて 直接 string filter に追加していくと

C++

string filter; filter \+= string\( "JPG \[ \*\.jpg, \*\.jpeg \]\\0\*\.jpg;\*\.jpeg\\0" \); filter \+= string\( "GIF \[ \*\.gif \]\\0\*\.gif\\0" \); \.\.\. // 省略

とやってみました。

すると、コンパイルが通り、動くのですが

拡張子のリスト部に 一つの文字列として

"JPG [ *.jpg, *.jpeg ]GIF [ *.gif ]PNG [ *.png ]..."

のようになってしまいます。

OPENFILENAME::lpstrFilterの型を見てみるとLPCTSTRとなっていました。

ビット演算で分岐 ( たとえば jpg, gif, mp3, mp4 を許可する 等のように ビットを立てた ものだけ 許可する ) し、

std::string で追加していって、

最後 ( "すべてのファイル [ *.* ]" ) まで入れた後に

OPENFILENAME::lpstrFilter に渡す...

っていうことは不可能なのでしょうか。

( 一応 C由来 の char型配列で

C

char strFilter\[10000\]; sprintf\( strFilter, "%s%s", strFilter, "image \[ \*\.gif, \*\.jpg, \*\.jpeg, \*\.png, \*\.bmp \]\\0\*\.gif;\*\.jpg;\*\.jpeg;\*\.png;\*\.bmp\\0" \); sprintf\( strFilter, "%s%s", strFilter, "movie \[ \.\.\. \]\\0\*\.mp4\\0" \); sprintf\( strFilter, "%s%s", strFilter, "All \[ \*\.\* \]\\0\*\.\*\\0\\0" \); ofn\.lpstrFilter = strFilter;

と試してみましたが、同じ結果でした。 )

呼び出し元 ( ウィンドウプロシージャ等 ) の問題ではなくOPENFILENAMEのメンバに対する問題だと
思うので 呼び出し元を省き、関数定義のみを提示します。

#include<string> // インデックス enum OPENFILEINDEX{ OF_INDEX_IMAGESET = 1, OF_INDEX_MOVIESET, OF_INDEX_SOUNDSET, OF_INDEX_TEXTSET, OF_INDEX_CPPSET, OF_INDEX_JAVASET, OF_INDEX_CSHARPSET, OF_INDEX_VBSET, OF_INDEX_DELPHISET, OF_INDEX_PYTHONSET, OF_INDEX_COMPRESSEDSET, OF_INDEX_EXCELSET, OF_INDEX_WORDSET, OF_INDEX_POWERPOINTSET, OF_INDEX_FONTSET, OF_INDEX_CURSORSET, OF_INDEX_GIF, OF_INDEX_JPG, OF_INDEX_PNG, OF_INDEX_BMP, OF_INDEX_MP4, OF_INDEX_MPG, OF_INDEX_FLV, OF_INDEX_AVI, OF_INDEX_WMV, OF_INDEX_MKV, OF_INDEX_MP3, OF_INDEX_WAV, OF_INDEX_3GP, OF_INDEX_3G2, OF_INDEX_TXT, OF_INDEX_DAT, OF_INDEX_DATA, OF_INDEX_SWF, OF_INDEX_EXE, OF_INDEX_DLL, OF_INDEX_JAVA, OF_INDEX_CLASS, OF_INDEX_JAR, OF_INDEX_HTML, OF_INDEX_CSS, OF_INDEX_JAVASCRIPT, OF_INDEX_VBS, OF_INDEX_VB, OF_INDEX_CS, OF_INDEX_BAT, OF_INDEX_PHP, OF_INDEX_PY, OF_INDEX_PYC, OF_INDEX_RB, OF_INDEX_PL, OF_INDEX_C, OF_INDEX_CC, OF_INDEX_CPP, OF_INDEX_O, OF_INDEX_OBJ, OF_INDEX_LIB, OF_INDEX_HEADER, OF_INDEX_ZIP, OF_INDEX_RAR, OF_INDEX_LZH, OF_INDEX_ISO, OF_INDEX_DOC, OF_INDEX_DOCX, OF_INDEX_XLS, OF_INDEX_XLSX, OF_INDEX_PPT, OF_INDEX_PPTX, OF_INDEX_ANI, OF_INDEX_CUR, OF_INDEX_ICO, OF_INDEX_TTF, OF_INDEX_OTF, OF_INDEX_LNK, OF_INDEX_URL, OF_INDEX_ALL }; // エラーコード #define OFDIALOG_ERROR_CANCELED \(-1\) #define OFDIALOG_ERROR_WRONGHNADLE \(-2\) #define OFDIALOG_ERROR_CANNOTFINDRES \(-3\) #define OFDIALOG_ERROR_INIT \(-4\) #define OFDIALOG_ERROR_CANNOTLOADRES \(-5\) #define OFDIALOG_ERROR_CANNOTLOADSTR \(-6\) #define OFDIALOG_ERROR_CANNOTLOCKRES \(-7\) #define OFDIALOG_ERROR_MEMALLOC \(-8\) #define OFDIALOG_ERROR_MEMLOCK \(-9\) #define OFDIALOG_ERROR_REGISTERMSGFAIL \(-10\) #define OFDIALOG_ERROR_STRUCT \(-11\) #define OFDAILOG_ERROR_BUFFER \(-12\) #define OFDIALOG_ERROR_INVALIDFILENAME \(-13\) #define OFDIALOG_ERROR_SUBCLASS \(-14\) #define OFDIALOG_ERROR_UNKNOWN \(-15\) using namespace std; // "ファイルを開く" ダイアログを表示する関数 int ShowOpenFile\( HWND hWnd, int DefaultIndex, const char \*DefaultDir, const char \*DefaultFileName, char \*result \){ OPENFILENAME ofn; string filter; // ファイル拡張子のフィルタ \( 文字列 \) char temp\[MAX_PATH\+1\]; int tempIndex; if\( DefaultIndex <= 0 \){ tempIndex = OF_INDEX_ALL; }else{ tempIndex = DefaultIndex; } // これをやらないと失敗する memset\( &ofn, 0, sizeof\(OPENFILENAME\) \); // ここでビット演算し、ビットが立っているものを追加するという処理にしたい。 // ですが今はビット演算を知りたいのではなく 文字列追加について知りたいので。 filter \+= string\( "image \[ \*\.gif, \*\.jpg, \*\.jpeg, \*\.png, \*\.bmp \]\\0\*\.gif;\*\.jpg;\*\.jpeg;\*\.png;\*\.bmp\\0" \); filter \+= string\( "movie \[ \.\.\. \]\\0\*\.mp4\\0" \); filter \+= string\( "All \[ \*\.\* \]\\0\*\.\*\\0\\0" \); ofn\.lpstrFilter = strFilter; ofn\.lStructSize = sizeof\(OPENFILENAME\); ofn\.hwndOwner = hWnd; ofn\.nFilterIndex = tempIndex; // 最初に指定するインデックス ofn\.lpstrInitialDir = DefaultDir; ofn\.lpstrFile = temp; // 戻り値用 ofn\.nMaxFile = MAX_PATH\+1; // 戻り値の最大の長さ ofn\.Flags = OFN_FILEMUSTEXIST; // フラグ if\( GetOpenFileName\( &ofn \) != 0 \){ strcpy\( result, temp \); return 0; }else{ DWORD r =CommDlgExtendedError\(\); if\( r == 0 \){ return OFDIALOG_ERROR_CANCELED; // キャンセルされた }else if\( r == CDERR_DIALOGFAILURE \){ return OFDIALOG_ERROR_WRONGHNADLE; // 無効なウィンドウハンドルが指定された等でダイアログ生成失敗 }else if\( r == CDERR_FINDRESFAILURE \){ return OFDIALOG_ERROR_CANNOTFINDRES; // リソースが見つからなかった }else if\( r == CDERR_INITIALIZATION \){ return OFDIALOG_ERROR_INIT; // メモリ不足等によりダイアログ初期化失敗 }else if\( r == CDERR_LOADRESFAILURE \){ return OFDIALOG_ERROR_CANNOTLOADRES; // リソースのロード失敗 }else if\( r == CDERR_LOADSTRFAILURE \){ return OFDIALOG_ERROR_CANNOTLOADSTR; // 指定した文字列のロード失敗 }else if\( r == CDERR_LOCKRESFAILURE \){ return OFDIALOG_ERROR_CANNOTLOCKRES; // 指定したリソースのロック失敗 }else if\( r == CDERR_MEMALLOCFAILURE \){ return OFDIALOG_ERROR_MEMALLOC; // 内部の構造体用のメモリ割り当てに失敗 }else if\( r == CDERR_MEMLOCKFAILURE \){ return OFDIALOG_ERROR_MEMLOCK; // ハンドルに関連付けられているメモリをロック失敗 }else if\( r == CDERR_REGISTERMSGFAIL \){ return OFDIALOG_ERROR_REGISTERMSGFAIL; // コモンダイアログボックス関数が呼び出した RegisterWindowMessage 関数が、エラーコードを返した }else if\( r == CDERR_STRUCTSIZE \){ return OFDIALOG_ERROR_STRUCT; // 該当するコモンダイアログボックス用の初期化構造体の lStructSize メンバが無効 }else if\( r == FNERR_BUFFERTOOSMALL \){ return OFDAILOG_ERROR_BUFFER; // 構造体の lpstrFile メンバが指すバッファが小さすぎて、ユーザーが指定したファイル名を格納できない。lpstrFile バッファの最初の 2 バイトは、名前全体を受け取るために必要なサイズを TCHAR 単位で格納します。 }else if\( r == FNERR_INVALIDFILENAME \){ return OFDIALOG_ERROR_INVALIDFILENAME; // ファイル名が無効 }else if\( r == FNERR_SUBCLASSFAILURE \){ return OFDIALOG_ERROR_SUBCLASS; // メモリ不足のため、リストボックスのサブクラス化失敗 }else{ return OFDIALOG_ERROR_UNKNOWN; } } }

( enum と #define と 関数プロトタイプは ヘッダに、関数定義は cppファイルに記述していますが、わかりやすくするために一つにまとめています。 )

※ ofnは OPENFILENAMEのオブジェクトとします。

[ 環境等 ]
言語 : C/C++ ( Windows API 実装 )
コンパイラ : MinGW
知りたいこと: "ファイルを開く"ダイアログ用のOPENFILENAME::lpstrFilterに設定する文字列データをビット演算でビットが立っているものを追加する方法

宜しくお願い致します。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C

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

Win32 API

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。