2012-05-04 12 views
8

我寫這個代碼來獲取文件名保存我的文件:如何在Win32中用GetSaveFileName保存文件?

#include "stdafx.h" 
#include <windows.h> 


int _tmain(int argc, _TCHAR* argv[]) 
{    
    OPENFILENAME ofn; 

    char szFileName[MAX_PATH] = ""; 

    ZeroMemory(&ofn, sizeof(ofn)); 

    ofn.lStructSize = sizeof(ofn); 
    ofn.hwndOwner = NULL; 
    ofn.lpstrFilter = (LPCWSTR)L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; 
    ofn.lpstrFile = (LPWSTR)szFileName; 
    ofn.nMaxFile = MAX_PATH; 
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 
    ofn.lpstrDefExt = (LPCWSTR)L"txt"; 

    GetSaveFileName(&ofn); 
    printf("the path is : %s\n", ofn.lpstrFile); 
    getchar(); 
    return 0; 
} 

但輸出是:

the path is : H 

爲什麼呢?難道我做錯了什麼 ?
我使用Windows 7的

+1

+1爲完整的例子和精心制定的問題。 –

回答

8

此行的Visual Studio 2008:

printf("the path is : %s\n", ofn.lpstrFile); 

應該用printf的寬字符版本。

wprintf(L"the path is : %s\n", ofn.lpstrFile); 
+1

+1你贏了......這一次。 :) –

+1

由於其他代碼(包括'lpstrFile'值)基於'_TCHAR',所以應該使用'_tprintf'代替:'_tprintf(_T(「路徑爲:%s \ n」),ofn .lpstrFile);' –

+2

-1此代碼仍然很危險,因爲緩衝區太小。 –

8

問題的根源是這些行:

char szFileName[MAX_PATH] = ""; 
... 
ofn.lpstrFile = (LPWSTR)szFileName; 
ofn.nMaxFile = MAX_PATH; 

這將創建的MAX_PATH字符的緩衝區,但它告訴GetSaveFileName功能,它是MAX_PATH 字符的緩衝區。當有人選擇長路徑名時,這可能會崩潰(或者無聲地踐踏記憶)。

贈品是演員。不要對編譯器或庫撒謊。他們不喜歡這樣的事情,最終他們總是會報仇。用下面的代替這些行:

WCHAR szFileName[MAX_PATH] = L""; 
... 
ofn.lpstrFile = szFileName; // no cast needed 
ofn.nMaxFile = MAX_PATH; 

現在所選的文件名將作爲一個寬字符的字符串返回。託尼獅子的答案是正確的在你需要使用wprintf,而不是printf打印的寬字符的字符串:

wprintf(L"the path is : %s\n", ofn.lpstrFile); // though I'd use szFileName at this point 

如果您需要在8位字符,而不是寬字符的字符串,可以使用調用WideCharToMultiByte 。但我一般會堅持使用寬字符的API。

除非您確切知道它在做什麼以及爲什麼在您的特定情況下有必要,否則永遠不會投。

-1

你們都錯了,這是一個簡單的C指針/堆棧問題。

// WRONG: 
char szFileName[MAX_PATH] = ""; 

這混淆數組和指針,可以聲明在棧上的陣列,但隨後改變其​​存儲器地址以指向數據部分爲空字符串。換句話說,一個緩衝區溢出。

// RIGHT: 
char szFileName[MAX_PATH]; 
ZeroMemory(szFileName, MAX_PATH); 

這將在棧上聲明一個字符數組,並將所有元素初始化爲空終止符。

希望有幫助!

+0

數組初始化符右側的文字字符串有特殊含義。聲明'char szFileName [MAX_PATH] =「」'; *不*創建指針。它將'szFileName [0]初始化爲'\ 0'',即空終止符。 –