1

[名前を付けて保存] ダイアログを表示する次のコード (抜粋) があります。

char FileName[MAX_PATH] = "TestImage.jpg"

...

lpofn.lStructSize = sizeof(OPENFILENAME);
lpofn.hwndOwner = hWnd;
lpofn.hInstance = GetWindowInstance (hWnd);
lpofn.lpstrFilter = "JPG - JPEG File\0*.JPG\0TIF - TIFF File\0*.TIF\0PNG File\0*.PNG\0BMP - Bitmat File\0*.BMP\0";
lpofn.lpstrCustomFilter = NULL;
lpofn.nMaxCustFilter = NULL;
lpofn.nFilterIndex = 0;
lpofn.lpstrFile = FileName;
lpofn.nMaxFile = MAX_PATH;
lpofn.lpstrFileTitle = NULL;
lpofn.nMaxFileTitle = NULL;
lpofn.lpstrInitialDir = NULL;
lpofn.lpstrTitle = NULL;
lpofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_EXPLORER;
lpofn.nFileOffset = 0;
lpofn.nFileExtension = 0;
lpofn.lpstrDefExt = NULL;
lpofn.lCustData = NULL;
lpofn.lpfnHook = &UpdateFilename;
lpofn.lpTemplateName = NULL;
if(!GetSaveFileName(&lpofn)) return;

...

例えば。- ユーザーは、デフォルトのファイル名 = "TestImage.jpg"、デフォルトのファイルの種類 = JPG として保存します。 - ユーザーは、ファイルの種類を PNG に変更します。

私は何か間違ったことをしていますか?GetSaveFileName() に拡張子を変更するように指示することは可能ですか、またはダイアログとしてカスタム保存する必要がありますか (例はありますか?)

Win32 API、VC6 を使用しています。

更新:フック関数は次のとおりです。

UINT CALLBACK UpdateFilename(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uiMsg)
    {
         case WM_NOTIFY:
          // Check for CDN_TYPECHANGE etc
              return FALSE;
    }

    return FALSE;
}

フック関数はブレークポイントで停止することに注意してください。フックが有効になっているときにダイアログの外観が変わる理由とそれを修正する方法を理解できるまで、意図的に CDN_TYPECHANGE の処理を​​続行しません。

4

2 に答える 2

3

提案されたファイル名には、静的文字列ではなくバッファを使用してください。

char szFile[MAX_PATH]; 
szFile[0] = '\0';
lpofn.lpstrFile= szFile; 
lpofn.nMaxFile = sizeof(szFile)/ sizeof(*szFile);

それに加えて、これは Win95 の時代にさかのぼるデフォルトの Windows の動作です。VS6.0 を使用しているため、まだこれらの DLL があります。私がしたことは、使用することでした:

lpofn.lpstrDefExt = (LPSTR)NULL

これにより、拡張機能が追加されなくなります。次に、戻ってきたときにlpofn.nFileExtensionをチェックして、どの拡張子が選択されているかを調べました。

if (lpofn.nFileExtension == 0)
{
// add default extension, no extension was selected/entered by user
}
else
{
 // there is an extension, save as entered.
}
于 2013-01-22T00:14:11.523 に答える
2

実行中にダイアログを更新するにはlpfnHook、構造体でコールバックへのポインターを指定し、コールバックに通知OPENFILENAMEを処理させる必要があります。CDN_TYPECHANGEダイアログaCDM_GETFILEPATHまたはCDM_GETSPECメッセージを送信して現在のファイル名を取得し、必要に応じて微調整してから、CDM_SETCONTROLTEXTメッセージを送信して編集フィールド(ファイル名編集フィールドのIDは0x442)を新しい値で更新できます。

更新:フックコードに問題はありません。 GetSaveFileName()Windows Vista以降は非推奨になり、Common Item Dialogに置き換えられました(そしてラッパーになりました) 。GSFNダイアログUIはXPのフックによって変更されないため、Vista +を使用する必要があります。この場合、フックを有効にすると、CIDを内部で呼び出すときにラッパーが異なる設定を使用するようになります。新しいCID機能の多くは、ファイル名文字列ではなくに基づいているIShellItemため、ラッパーは古いスタイルのファイル名として表現できないものをすべて削除し、ダイアログをXP以前の古いスタイルのGSFNダイアログのように見せます。したがって、表示されているのは、Vista+での通常の動作です。GetSaveFileName()気に入らない場合は、GetSaveFileName()もう使用しないでください。新しいを使用するIFileSaveDialog代わりにインターフェース。実際、複数のファイルタイプを構成し、そのうちの1つをデフォルトの拡張子として指定してから、デフォルトの拡張子と一致する初期ファイル名を設定すると、ファイル拡張子がネイティブに変更されます。IFileDialogEventsただし、必要に応じて、コードにインターフェイスを実装してOnTypeChange通知を受信し、そのIFileDialog::SetFileName()メソッドを使用して、表示されているファイル名を必要に応じて更新することもできます。

于 2013-01-22T03:25:06.097 に答える