您的位置:首页 > 其它

使用文件和通用对话框——模仿windows记事本程序Part2

2012-11-07 15:50 399 查看

通用文件对话框

最常用的打开和保存文件的对话框分別通过GetOpenFileName()和GetSaveFileName()来调用, 它们两个都要一个OPENFILENAME结构体作参数.

OPENFILENAME ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(GetOpenFileName(&ofn))
{
	// Do something usefull with the filename stored in szFileName
}


请注意用了ZeroMemory()对结构体清零.这通常是个好的习惯,因为有些API对你传给的不用的参数要设为NULL很挑剔.用这种方法就不需要对每个不用的成员进行设置

了.

  LpstrFilter值指向一个双NULL终止符的字符串,并且从例子中看到有数个 ''\0'',包括结尾的那个...编译器会在结尾加上第二个,就像它对字符串常量通常所做的一样(一般不用自己去加).这个字符串中的空字符把其分成多个过滤器,每个有两个部分.第一个过滤器有描述''TextFiles (*.txt)'',通配符在这里不是必需的,接下来的部分是第一个过滤器的实际的通配符,”*.txt”.对第二个过滤器做同样的处理,除了它是一个所有文件的通用过滤器之外.可以随你喜欢加不同的过滤器.

  LpstrFile指向配置来保存文件名的內存,因为文件名不能长于MAX_PATH,所以也把这个值当作了此內存的大小.

  几个标志表明了对话框对允许用戶输入已存在的文件(我们只想打开,不想创建)并隠藏了我们不打算支持的以只读方式打开的选项.最后我们提供了一个默认的文件扩展名,所以如果用戶输入了''foo'',而沒有找到,那么它会在最后放棄之前去试图打开''foo.txt''.

  选择保存文件的代码和打开文件的代码几乎一样,除了调用GetSaveFileName()中我们需要改变一些标志以使选项更适合于保存文件.

OPENFILENAME ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(GetOpenFileName(&ofn))
{
      // Do something usefull with the filename stored in szFileName
}


对createFile()的调用中,GENERIC_READ意即只想有读的权限.FILE_SHARE_READ的意思是如果其它的程序也在打开的时候打开它也可以,但是它们也要是只读才行,它们要是在我们读的时候在对其进行写操作就不行.OPEN_EXISTING意思是只打开已经存在的文件,不要创建它,也不要覆盖它.

  一旦打开了文件并检查了CreateFile()调用成功后,再来检查文件的大小以便知道要配置多少內存来读入整个文件.于是配置內存,并检查配置的成功与否,用ReadFile()把文件从硬盘读到內存中来.API函数不会知道什么文本文件之类的消息所以它们不能读入文本的一行,或在的字符串后加上一个NULL终止符.这就是为什么要额外地配置一个字节以便在读入整个文件后可以自己加上一个NULL,这样就可以把我们的整个缓冲区当作一个单字符串当为参数传给SetWindowText().

  一旦所有的操作都成功了我们就把成功变量设为TRUE,并在函数的末尾处作一些清除工作,在函数最终返回到调用者之前释放配置的內存并关闭文件的句柄

与读文件十分类似,写文件的函数只有一点不同.首先在调用CreateFile()的时候要求有读权限,而且文件应该总是新创建(如果已经存在则它将会被打开并清除),如果不存在则它会被以常规属性创建.

贴代码了:

#include <Windows.h>
#include "resource.h"

#define IDR_MAINMENU                    102
#define ID_FILE_EXIT                    40001
#define ID_FILE_OPENONE                    40002
#define ID_FILE_S***EAS                  40003
#define ID_FILE_NEWONE                     40004
#define IDC_MAIN_EDIT                   101

BOOL LoadTextFileToEdit(HWND hEdit, LPCTSTR pszFileName)
{
	HANDLE hFile;
	BOOL bSuccess = FALSE;
	hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
		OPEN_EXISTING, 0, NULL);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		DWORD dwFileSize;
		dwFileSize = GetFileSize(hFile, NULL);
		if(dwFileSize != 0xFFFFFFFF)
		{
			LPSTR pszFileText;
			pszFileText = (LPSTR)GlobalAlloc(GPTR, dwFileSize + 1);
			if(pszFileText != NULL)
			{
				DWORD dwRead;

				if(ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL))
				{
					pszFileText[dwFileSize] = 0; // 
					if(SetWindowText(hEdit, pszFileText))
						bSuccess = TRUE; //
				}
				GlobalFree(pszFileText);
			}
		}
		CloseHandle(hFile);
	}
	return bSuccess;
}

BOOL SaveTextFileFromEdit(HWND hEdit, LPCTSTR pszFileName)
{
	HANDLE hFile;
	BOOL bSuccess = FALSE;
	hFile = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL,
		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		DWORD dwTextLength;
		dwTextLength = GetWindowTextLength(hEdit);
		if(dwTextLength > 0)
		{
			LPSTR pszText;
			DWORD dwBufferSize = dwTextLength + 1;
			pszText = (LPSTR)GlobalAlloc(GPTR, dwBufferSize);
			if(pszText != NULL)
			{
				if(GetWindowText(hEdit, pszText, dwBufferSize))
				{
					DWORD dwWritten;

					if(WriteFile(hFile, pszText, dwTextLength, &dwWritten, NULL))
						bSuccess = TRUE;
				}
				GlobalFree(pszText);
			}
		}
		CloseHandle(hFile);
	}
	return bSuccess;
}

void DoFileOpen(HWND hwnd)
{
	OPENFILENAME ofn;
	char szFileName[MAX_PATH]= "";
	ZeroMemory(&ofn, sizeof(ofn));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hwnd;
	ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All File (*.*)\0*.*\0";
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrDefExt = "txt";
	ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	if (GetOpenFileName(&ofn))
	{
		HWND hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
		LoadTextFileToEdit(hEdit, szFileName);
	}
}

void DoFileSaveAs(HWND hwnd)
{
	OPENFILENAME ofn;
	char szFileName[MAX_PATH]= "" ;
	ZeroMemory(&ofn, sizeof(ofn));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hwnd;
	ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All File (*.*)\0*.*\0";
	ofn.lpstrFile = szFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrDefExt = "txt";
	ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
	if(GetSaveFileName(&ofn))
	{
		HWND hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
		SaveTextFileFromEdit(hEdit, szFileName);
	}
}

const char g_szClassName[] = "myWindowClass";

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_CREATE:
		{
			HWND hEdit;
			HFONT hDefFont;
			hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"Edit","",WS_CHILD|WS_VISIBLE
				|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,
				0,0,100,100,hwnd,(HMENU)IDC_MAIN_EDIT,GetModuleHandle(NULL),NULL);
			if(hEdit == NULL)
				MessageBox(hwnd,"Create Edit Failed","Error",MB_OK|MB_ICONERROR);
			hDefFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
			SendMessage(hEdit,WM_SETFONT,(WPARAM)hDefFont,MAKELPARAM(FALSE,0));
		}
		break;
	case WM_SIZE:
		{
			HWND hEdit;
			RECT rect;
			GetClientRect(hwnd,&rect);
			hEdit = GetDlgItem(hwnd,IDC_MAIN_EDIT);
			SetWindowPos(hEdit,NULL,0,0,rect.right,rect.bottom,SWP_NOZORDER);
		}
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_FILE_EXIT:
			PostMessage(hwnd,WM_CLOSE,0,0);
			break;
		case ID_FILE_NEWONE:
			SetDlgItemText(hwnd, IDC_MAIN_EDIT, "");
			break;
		case ID_FILE_OPENONE:
			DoFileOpen(hwnd);
			break;
		case ID_FILE_S***EAS:
			DoFileSaveAs(hwnd);
			break;
		}
		break;
	case WM_CLOSE:
		DestroyWindow(hwnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;
	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINMENU);
	wc.lpszClassName = g_szClassName;
	wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		g_szClassName,
		"Edit",
		WS_OVERLAPPEDWINDOW,
		200, 200, 400, 400,
		NULL, NULL, hInstance, NULL);
	if(hwnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐