简体   繁体   English

如何在win32中使用GetSaveFileName保存文件?

[英]how to save file with GetSaveFileName in win32?

I write this code to get fileName to save my file : 我写这个代码来获取fileName来保存我的文件:

#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;
}

But the output is : 但输出是:

 the path is : H 

why ? 为什么? Am I doing something wrong ? 难道我做错了什么 ?
I'm using Visual Studio 2008 on Windows 7. 我在Windows 7上使用Visual Studio 2008。

The root problem is in these lines: 根本问题在于:

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

This creates a buffer of MAX_PATH characters, but it tells the GetSaveFileName function that it's a buffer of MAX_PATH wide characters. 这将创建一个MAX_PATH字符的缓冲区,但它告诉GetSaveFileName函数它是MAX_PATH 字符的缓冲区。 This is likely to crash (or silently trample memory) when someone chooses a long path name. 当有人选择长路径名时,这很可能会崩溃(或者无声地践踏内存)。

The giveaway is the cast. 赠品是演员。 Don't lie to the compiler or the libraries. 不要欺骗编译器或库。 They don't like that, and they'll always get their revenge in the end. 他们不喜欢这样,他们最终会报复。 Replace those lines with this: 用这个替换这些行:

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

Now the selected filename will be returned as a string of wide characters. 现在,所选文件名将作为宽字符串返回。 Tony The Lion's answer is correct in that that you need to use wprintf rather than printf to print strings of wide characters: Tony The Lion的答案是正确的,因为您需要使用wprintf而不是printf来打印宽字符串:

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

If you need the string in 8-bit characters instead of wide characters, you can use WideCharToMultiByte. 如果您需要8位字符而不是宽字符的字符串,则可以使用WideCharToMultiByte。 But I would just stick with the wide character APIs in general. 但我总是坚持使用宽字符API。

Never cast unless you know exactly what it does and why it's necessary in your particular case. 除非你确切知道它的作用以及为什么在你的特定情况下它是必要的,否则永远不要施放。

This line: 这一行:

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

should use the wide char version of printf. 应该使用printf的宽字符版本。

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

You're both wrong, it's a simple C pointer/stack issue. 你错了,这是一个简单的C指针/堆栈问题。

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

This confuses arrays and pointers, you declare an array on the stack, but then change its memory address to point to an empty string in the data section. 这会混淆数组和指针,您在堆栈上声明了一个数组,但随后将其内存地址更改为指向数据部分中的空字符串。 In other words, a buffer overflow. 换句话说,缓冲区溢出。

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

This declares a character array on the stack and initializes all elements to null terminator. 这在堆栈上声明了一个字符数组,并将所有元素初始化为null终止符。

Hope that helps! 希望有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM