`
leili
  • 浏览: 174811 次
社区版块
存档分类
最新评论

《PicSi的实现细节》 第3节 窗口类CPicSiCreatorDlg的定义

阅读更多
       这一节是本系列文章中最重要的部分,因为CPicsiCreatorDlg类是Main子窗口的实现类,它是PicSi的功能主体。有了第2节作为基础,相信大多数朋友对CPicSiCreatorDlg的主框架是不陌生的。因此,本节将重点阐述关键思路,而代码的实现细节不在文中说明了。我会在文章的末尾将所涉及的代码贴出,若理解过程中碰到什么问题或者疑问,可随时提出。
      CPicsiCreatorDlg与CAboutDlg一样,都是CDialogImpl的派生类。因此它也通过Create方法来创建实例对象;同时,它也有自己的消息映射,能够处理窗口消息。
   题外话:可能有的朋友觉得类名CPicsiDreatorDlg太长,对的,我也觉得有点长。不过,好的命名规范是需要尽量做到见名知义的,名称长点没关系,Ctrl + C/V,一点都不慢,还不易出错。
      首先看CPicsiCreatorDlg的成员变量,窗口类的成员变量一般分为两类:控制成员变量和数据成员变量。建议将它们分成两团定义,而不要交叉定义,这样可使代码更清晰一些。
      控制成员变量很好理解,就是窗口中控制(控件)在类中对应的变量。我们总是通过控制成员变量来对控制加以维护的。数据成员变量是算法所需的变量,如本例中,m_fileList是一个链表,它用来保存文件名列表,而m_strOutputPath即输出路径字符串。
      接下来就需要定义若干方法来响应窗口消息了。Windows编程的本质就是“以消息为基础,事件驱动之(Message based and Event driven)”。也就是说,任何一个Windows程序,它的整个生命周期说白了就是在不停地捕获消息,不停地调用方法对消息进行响应。因此,窗口类有着非常明显的特点,其主体一定是消息映射和响应方法。同时,每个类又可能含有一些成员变量以及一些私有成员方法,供消息的响应方法使用或调用。当然,它也可以拥有少量的公共方法,供父窗口调用。
      每个窗口类都应该响应WM_INITDIALOG消息,窗口在被初始化时,它将被抛出,用OnInitDialog方法响应它,OnInitDialog将实现窗口相关的初始化。此外,如果窗口尺寸是可调整的话,WM_SIZE消息一般也需被处理,定义OnSize方法来响应该消息。在OnSize方法的末尾,将bHandled置为FALSE,表示WM_SIZE消息并不被当前窗口类独占,它还可以被其它窗口处理。而return 1表示允许操作系统自己再对WM_SIZE做进一步的处理,比如重绘窗口背景;如果return 0的话,操作系统是不会做进一步操作的,这对于调整窗口大小来说,可能会造成程序异常。当然,大多数消息的响应方法返回值都应该是0。
      AddFile方法是CPicsiCreatorDlg类唯一一个public方法,它的作用是将szFilePath所指向的文件名添加到m_fileList链表中,并且在Listview控制中显示该文件的名称、尺寸、创建时间等信息。AddFile方法在程序中仅仅被主窗口调用,参见MainDlg::OnDropFIles方法。
      接下来就是依次响应控制消息:
  • IDC_BTN_SETPATH - 用户单击Set按钮,设置输出路径;
  • IDC_BTN_OPEN - 用户单击Open按钮,打开输出目录;
  • IDC_BTN_CLEAR - 用户单击Clear按钮,清空文件列表;
  • IDC_BTN_OK - 用户单击Open按钮,开始生成内涵图;
  • IDC_LIST_ORDINARY通知消息NM_DBLCLK - 用户在Listview控制中双击鼠标左键,打开选中的文件;
  • IDC_LIST_ORDINARY通知消息NM_RCLICK - 用户在Listview控制右击鼠标,弹出右键菜单;
  • ID_POP1_OPEN - 用户选中右键菜单项Open,打开选中的文件;
  • ID_POP1_DELETE - 用户选中右键菜单项Delete,删除选中的文件;
  • ID_POP1_UP - 用户选中右键菜单项Up,将选中的文件往上移一位;
  • ID_POP1_DOWN - 用户选中右键菜单项Down,将选中的文件往下移一位;
  • ID_POP1_TOP - 用户选中右键菜单项Top,将选中的文件置顶;
  • ID_POP1_BOTTOM - 用户选中右键菜单项Bottom,将选中的文件置底。
      简要说明一下CPicsiCreatorDlg类中的私有方法:
  • get_appdata_path - 获得PicSi配置文件在AppData目录的全路径,配置文件里保存着输出路径(output path)。
  • read_output_path - 从PicSi配置文件中读取输出路径并保存到m_strOutputPath成员变量中。
  • write_output_path - 将输出路径字符串m_strOutputPath写入PicSi配置文件中。
  • IsValid - 当用户单击OK按钮后,程序将首先检查文件列表是否符合规则“至少两个文件,首个文件必须是jpg文件”,只有再确认之后再正式生成内涵图。IsVaild起到检查文件列表是否符合规则的作用。
  • get_rar_exe_path - 获得rar.exe文件的全路径,rar.exe用于压缩文件。
  • get_copy_bat_path - 获得copy.bat文件的全路径,copy.bat包含copy命令,拼接jpg和rar文件,制作内涵图。
  • get_temporary_rar_path - 获得临时rar文件的路径。
  • delete_temporary_rar - 删除临时rar文件。
  • build_rar_command_line - 装配rar.exe命令。
  • build_copy_command_line - 装配copy命令。
  • execute_subprocess - 执行子进程,传入参数即命令行字符串。
  • shell_open_selected_file - 打开被选中的文件。
  • refresh_list_view - 刷新Listview。
CPicSiCreatorDlg窗口类的所有代码如下所示:
// CPicsiCreatorDlg

class CPicsiCreatorDlg : public CDialogImpl<CPicsiCreatorDlg>
{
private:
	CButton m_btnOK;
	CButton m_btnClear;
	CStatic m_static;
	CEdit m_editPath;
	CButton m_btnSet;
	CButton m_btnOpen;
	CListViewCtrl m_list;

	ATL::CAtlList<WTL::CString> m_fileList;
	WTL::CString m_strOutputPath;

public:
	enum { IDD = IDD_DLG_CREATOR };

	void AddFile(LPCTSTR szFilePath) throw()
	{
		ATLASSERT(szFilePath != NULL);
		POSITION pos = m_fileList.GetHeadPosition();
		// check if alreay added
		while(pos != NULL) {
			WTL::CString strFilePath = m_fileList.GetAt(pos);
			if(::lstrcmpi(szFilePath, strFilePath) == 0) {
				WTL::CString strMsg = _T("You have already added file \"");
				strMsg += szFilePath;
				strMsg += _T("\"!");
				PS_MessageBox(strMsg, MB_ICONWARNING);
				return;
			} // end if
			m_fileList.GetNext(pos);
		} // end while
		int nCount = m_list.GetItemCount();
		WTL::CString strFilename;
		PS_GetFilename(szFilePath, strFilename);
		m_list.AddItem(nCount, 0, strFilename);
		// add size
		OFSTRUCT os;
		HANDLE hFile = (HANDLE)::OpenFile(::CT2A(szFilePath), &os, OF_READ);
		BY_HANDLE_FILE_INFORMATION fileinfo;
		::GetFileInformationByHandle(hFile, &fileinfo);
		TCHAR szSize[20];
		_stprintf_s(szSize, _T("%d KB"), fileinfo.nFileSizeLow / 1024);
		m_list.AddItem(nCount, 1, szSize);
		// add creation time
		SYSTEMTIME st;
		FileTimeToSystemTime(&fileinfo.ftCreationTime, &st);
		TCHAR szCreationTime[24];
		_stprintf_s(szCreationTime, _T("%d/%02d/%02d %02d:%02d"), st.wYear, st.wMonth, st.wDay, (st.wHour + 8)%24, st.wMinute);
		m_list.AddItem(nCount, 2, szCreationTime);
		// add file
		m_fileList.AddTail(szFilePath);
	}

	//message handler
	BEGIN_MSG_MAP(CPicsiCreatorDlg)
		MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
		MESSAGE_HANDLER(WM_SIZE, OnSize)
		COMMAND_ID_HANDLER(IDOK, OnOK)
		COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		COMMAND_ID_HANDLER(IDC_BTN_SETPATH, OnButtonSetpath)
		COMMAND_ID_HANDLER(IDC_BTN_OPEN, OnButtonOpen)
		COMMAND_ID_HANDLER(IDC_BTN_CLEAR, OnButtonClear)
		COMMAND_ID_HANDLER(IDC_BTN_OK, OnButtonOK)
		NOTIFY_HANDLER(IDC_LIST_ORDINARY, NM_DBLCLK, OnListDoubleClick)
		NOTIFY_HANDLER(IDC_LIST_ORDINARY, NM_RCLICK, OnListRightClick)
		COMMAND_ID_HANDLER(ID_POP1_OPEN, OnMenuOpen)
		COMMAND_ID_HANDLER(ID_POP1_DELETE, OnMenuDelete)
		COMMAND_ID_HANDLER(ID_POP1_UP, OnMenuUp)
		COMMAND_ID_HANDLER(ID_POP1_DOWN, OnMenuDown)
		COMMAND_ID_HANDLER(ID_POP1_TOP, OnMenuTop)
		COMMAND_ID_HANDLER(ID_POP1_BOTTOM, OnMenuBottom)
	END_MSG_MAP()

	LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		m_btnOK.Attach(GetDlgItem(IDC_BTN_OK));
		m_btnClear.Attach(GetDlgItem(IDC_BTN_CLEAR));
		m_static.Attach(GetDlgItem(IDC_STATIC));
		m_editPath.Attach(GetDlgItem(IDC_EDIT_PATH));
		m_btnSet.Attach(GetDlgItem(IDC_BTN_SETPATH));
		m_btnOpen.Attach(GetDlgItem(IDC_BTN_OPEN));
		m_list.Attach(GetDlgItem(IDC_LIST_ORDINARY));
		// add colums
		LVCOLUMN lvc = { 0 };
		lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
		lvc.fmt = LVCFMT_CENTER;
		lvc.pszText = _T("File Name");
		lvc.cx = 300;
		m_list.InsertColumn(0, &lvc);
		lvc.pszText = _T("File Size");
		lvc.cx = 80;
		m_list.InsertColumn(1, &lvc);
		lvc.pszText = _T("Creation Time");
		lvc.cx = 145;
		m_list.InsertColumn(2, &lvc);
		
		if( !read_output_path() || m_strOutputPath.GetLength() <= 0)
			m_strOutputPath.Empty();
		m_editPath.SetWindowText(m_strOutputPath);
		return TRUE;
	}
	// OnSize
	LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if( wParam != SIZE_MINIMIZED ) {
			int nWidth = LOWORD(lParam);
			int nHeight = HIWORD(lParam);
			// change layout
			m_static.SetWindowPos(NULL, 4, 8, 88, 16, SWP_NOACTIVATE | SWP_NOZORDER);
			m_editPath.SetWindowPos(NULL, 92, 4, 228, 24, SWP_NOACTIVATE | SWP_NOZORDER);
			m_btnSet.SetWindowPos(NULL, 320, 4, 22, 24, SWP_NOACTIVATE | SWP_NOZORDER);
			m_btnOpen.SetWindowPos(NULL, 344, 4, 48, 24, SWP_NOACTIVATE | SWP_NOZORDER);
			m_btnOK.SetWindowPos(NULL, 420, 4, 48, 24, SWP_NOACTIVATE | SWP_NOZORDER);
			m_btnClear.SetWindowPos(NULL, 470, 4, 48, 24, SWP_NOACTIVATE | SWP_NOZORDER);
			m_list.SetWindowPos(NULL, 0, 32, nWidth, nHeight - 32, SWP_NOACTIVATE | SWP_NOZORDER);
		}
		bHandled = FALSE;
		return 1;
	}
	LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		//EndDialog(wID);
		return 0;
	}
	LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		//EndDialog(wID);
		return 0;
	}
	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		bHandled = FALSE;
		return 1;
	}
	LRESULT OnButtonSetpath(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		CFolderDialog dlg(NULL,_T("Set Output Directory"), BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS);
		if(m_strOutputPath != _T(""))
			dlg.SetInitialFolder(m_strOutputPath, TRUE);
		if( dlg.DoModal() == IDOK ) {
			m_strOutputPath = dlg.GetFolderPath();
			m_editPath.SetWindowText(m_strOutputPath);
			if( !write_output_path() )
				PS_MessageBox(_T("Save output path failed!"), MB_ICONWARNING);
		}
		return 0;
	}
	LRESULT OnButtonOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		::ShellExecute(NULL, _T("open"), NULL, NULL, m_strOutputPath, SW_NORMAL);
		return 0;
	}
	LRESULT OnButtonClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		m_list.DeleteAllItems();
		m_fileList.RemoveAll();
		return 1;
	}
	LRESULT OnButtonOK(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		if(m_strOutputPath.IsEmpty()) {
			PS_MessageBox(_T("Output cannot be empty, set output path first!"), MB_ICONWARNING);
			return 0;
		}
		if(!IsValid() ){
			PS_MessageBox(_T("At least two files and the first one must be a *.jpg file!"), MB_ICONERROR);
			return 0;
		}
		if( !delete_temporary_rar() ) {
			PS_MessageBox(_T("Clear temporary rar file failed!"), MB_ICONERROR);
			return 0;
		}
		WTL::CString strCommandLine;		
		if(!build_rar_command_line(strCommandLine)) {
			PS_MessageBox(_T("Create connotative jpg failed!"), MB_ICONERROR);
			return 0;
		}
		if(!execute_subprocess(strCommandLine.GetBuffer(128))) {
			PS_MessageBox(_T("Create connotative jpg failed!"), MB_ICONERROR);
			return 0;
		}
		if(!build_copy_command_line(strCommandLine)) {
			PS_MessageBox(_T("Create connotative jpg failed!"), MB_ICONERROR);
			delete_temporary_rar();
			return 0;
		}
		if(!execute_subprocess(strCommandLine.GetBuffer(128))) {
			delete_temporary_rar();
			return 0;
		}
		delete_temporary_rar();
		PS_MessageBox(_T("Create connotative jpg succeed!"), MB_ICONINFORMATION);		
		return 0;
	}
	LRESULT OnListDoubleClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
	{
		shell_open_selected_file();
		return 0;
	}
	LRESULT OnListRightClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return 0;
		CMenu menu;
		menu.LoadMenu(IDR_MENU_POP);
		CMenuHandle oMenu = menu.GetSubMenu(0);
		if(nSelect == 0) {
			oMenu.EnableMenuItem(ID_POP1_UP, MF_BYCOMMAND | MF_GRAYED);
			oMenu.EnableMenuItem(ID_POP1_TOP, MF_BYCOMMAND | MF_GRAYED);
		}
		if(nSelect == m_list.GetItemCount() - 1) {
			oMenu.EnableMenuItem(ID_POP1_DOWN, MF_BYCOMMAND | MF_GRAYED);
			oMenu.EnableMenuItem(ID_POP1_BOTTOM, MF_BYCOMMAND | MF_GRAYED);
		}
		POINT pt;
		::GetCursorPos(&pt);
		oMenu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, m_hWnd);
		return 0;
	}
	LRESULT OnMenuOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		shell_open_selected_file();
		return 0;
	}
	LRESULT OnMenuDelete(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return 0;
		POSITION pos = m_fileList.GetHeadPosition();
		for(int i = 0; i < nSelect; i++)
			m_fileList.GetNext(pos);
		m_fileList.RemoveAt(pos);
		refresh_list_view();
		return 0;
	}
	LRESULT OnMenuUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return 0;
		POSITION pos = m_fileList.GetHeadPosition();
		for(int i = 0; i < nSelect; i++)
			m_fileList.GetNext(pos);
		POSITION posPrev = pos;
		m_fileList.GetPrev(posPrev);
		m_fileList.SwapElements(pos, posPrev);
		refresh_list_view();
		return 0;
	}
	LRESULT OnMenuDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return 0;
		POSITION pos = m_fileList.GetHeadPosition();
		for(int i = 0; i < nSelect; i++)
			m_fileList.GetNext(pos);
		POSITION posLatter = pos;
		m_fileList.GetNext(posLatter);
		m_fileList.SwapElements(pos, posLatter);
		refresh_list_view();
		return 0;
	}
	LRESULT OnMenuTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return 0;
		POSITION pos = m_fileList.GetHeadPosition();
		for(int i = 0; i < nSelect; i++)
			m_fileList.GetNext(pos);
		m_fileList.MoveToHead(pos);
		refresh_list_view();
		return 0;
	}
	LRESULT OnMenuBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return 0;
		POSITION pos = m_fileList.GetHeadPosition();
		for(int i = 0; i < nSelect; i++)
			m_fileList.GetNext(pos);
		m_fileList.MoveToTail(pos);
		refresh_list_view();
		return 0;
	}

private:
	// get appdata path
	BOOL get_appdata_path(WTL::CString& strPath) throw()
	{
		if(!PS_GetAppDataDirectory(strPath))
			return FALSE;
		PS_PathAppendBackslash(strPath);
		strPath += _T("PicSi");
		if( !PS_IsDirectory(strPath) ) {
			if( ::CreateDirectory(strPath, NULL) == 0 )
				return FALSE;
		}
		strPath += _T("\\cfg");
		return TRUE;
	}
	// read output path
	BOOL read_output_path() throw()
	{
		CString strAppdataPath;
		if(!get_appdata_path(strAppdataPath))
			return FALSE;
		ATL::CComPtr<IStream> spStream;
		HRESULT hr = ::SHCreateStreamOnFile(strAppdataPath, STGM_READ | STGM_SHARE_DENY_WRITE, &spStream);
		if(FAILED(hr))
			return FALSE;
		ULONG nCount;
		hr = spStream->Read(m_strOutputPath.GetBufferSetLength(MAX_PATH), MAX_PATH, &nCount);
		m_strOutputPath.ReleaseBuffer();
		if(FAILED(hr))
			return FALSE;
		return TRUE;
	}
	// write output path
	BOOL write_output_path() throw()
	{
		CString strAppdataPath;
		if(!get_appdata_path(strAppdataPath))
			return FALSE;
		ATL::CComPtr<IStream> spStream;
		HRESULT hr = ::SHCreateStreamOnFile(strAppdataPath, STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, &spStream);
		if(FAILED(hr))
			return FALSE;
		ULONG nCount;
		hr = spStream->Write(m_strOutputPath, MAX_PATH, &nCount);
		if(FAILED(hr))
			return FALSE;
		return TRUE;
	}
	// check valid
	BOOL IsValid() throw()
	{
		int nCount = m_list.GetItemCount();
		if(nCount < 2)
			return FALSE;
		TCHAR szText[MAX_PATH];
		int nTotal = m_list.GetItemText(0, 0, szText, MAX_PATH);
		WTL::CString strPath = szText;
		strPath.MakeLower();
		int nPos = strPath.Find(_T(".jpg"));
		if(nPos < 0 || nPos < nTotal - 4)
			return FALSE;
		return TRUE;
	}
	// get rar exe path
	BOOL get_rar_exe_path(WTL::CString& strRarExePath) throw()
	{
		if(!PS_GetInstallationDirectory(strRarExePath))
			return FALSE;
		else {
			if(!PS_PathAppendBackslash(strRarExePath))
				return FALSE;
			strRarExePath += _T("Rar.exe");
		}
		return TRUE;
	}
	// get copy bat path
	BOOL get_copy_bat_path(WTL::CString& strCopyBatPath) throw()
	{
		if(!PS_GetInstallationDirectory(strCopyBatPath))
			return FALSE;
		else {
			if(!PS_PathAppendBackslash(strCopyBatPath))
				return FALSE;
			strCopyBatPath += _T("copy.bat");
		}
		return TRUE;
	}
	// get temporary rar path
	BOOL get_temporary_rar_path(WTL::CString& strPath) throw()
	{
		strPath = m_strOutputPath;
		if(!PS_PathAppendBackslash(strPath))
			return FALSE;
			strPath += _T("picsi_temporary.rar");
		return TRUE;
	}
	// delete temporary rar
	BOOL delete_temporary_rar() throw()
	{
		WTL::CString strRarPath;
		get_temporary_rar_path(strRarPath);
		if( ::DeleteFile(strRarPath) == 0  && ::GetLastError() != ERROR_FILE_NOT_FOUND)
			return FALSE;
		return TRUE;
	}
	// build command line
	BOOL build_rar_command_line(WTL::CString& strCmd) throw()
	{
		if( !get_rar_exe_path(strCmd) )
			return FALSE;
		PS_AddDoubleQuotationMarks(strCmd);
		strCmd += _T(" a -ep1 ");
		WTL::CString strRarPath;
		if( !get_temporary_rar_path(strRarPath) )
			return FALSE;
		PS_AddDoubleQuotationMarks(strRarPath);
		strCmd += strRarPath;
		// append source file name
		WTL::CString strTmp;
		POSITION pos = m_fileList.GetHeadPosition();
		m_fileList.GetNext(pos);
		while(pos != NULL) {
			strTmp = m_fileList.GetAt(pos);
			PS_AddDoubleQuotationMarks(strTmp);
			strCmd += _T(" ");
			strCmd += strTmp;
			m_fileList.GetNext(pos);
		}		
		return TRUE;
	}
	// build copy command line
	BOOL build_copy_command_line(WTL::CString& strCmd) throw()
	{
		if( !get_copy_bat_path(strCmd) )
			return FALSE;
		PS_AddDoubleQuotationMarks(strCmd);
		strCmd += _T(" ");
		// append jpg file
		WTL::CString strJpgPath = m_fileList.GetHead();
		PS_AddDoubleQuotationMarks(strJpgPath);
		strCmd += strJpgPath;
		strCmd += _T(" ");
		// append rar file
		WTL::CString strRarPath;
		if( !get_temporary_rar_path(strRarPath) )
			return FALSE;
		PS_AddDoubleQuotationMarks(strRarPath);
		strCmd += strRarPath;
		strCmd += _T(" ");
		// append result file
		WTL::CString strResultFile;
		TCHAR szFilename[MAX_PATH];
		m_list.GetItemText(0, 0, szFilename, MAX_PATH);
		PS_GetFilename(szFilename, strResultFile);
		PS_PathAppendBackslash(m_strOutputPath);
		strResultFile = m_strOutputPath + strResultFile;
		PS_AddDoubleQuotationMarks(strResultFile);
		strCmd += strResultFile;
		return TRUE;
	}
	// execute subprocess
	BOOL execute_subprocess(LPTSTR szCommandLine) throw()
	{
		ATLASSERT(szCommandLine != NULL);
		STARTUPINFO si = { 0 };
		si.cb = sizeof(si);
		PROCESS_INFORMATION pi = { 0 };
		if( !CreateProcess( NULL, szCommandLine,
							NULL, NULL, FALSE, CREATE_NO_WINDOW,
							NULL, NULL, &si, &pi ) ) {
			DWORD dwCode = ::GetLastError();
			return FALSE;
		}
		WaitForSingleObject( pi.hProcess, INFINITE );
		CloseHandle( pi.hProcess );
		CloseHandle( pi.hThread );
		return TRUE;
	}
	// shell open selected file
	void shell_open_selected_file() throw()
	{
		int nSelect = m_list.GetSelectedIndex();
		if(nSelect < 0)
			return;
		POSITION pos = m_fileList.GetHeadPosition();
		for(int i = 0; i < nSelect; ++i)
			m_fileList.GetNext(pos);
		::ShellExecute(NULL, _T("open"), m_fileList.GetAt(pos), NULL, NULL, SW_NORMAL);
	}
	// refresh list view
	void refresh_list_view() throw()
	{
		m_list.DeleteAllItems();
		POSITION pos = m_fileList.GetHeadPosition();
		WTL::CString strFilePath;
		int i = 0;
		while(pos != NULL) {
			strFilePath = m_fileList.GetAt(pos);
			WTL::CString strFilename;
			PS_GetFilename(strFilePath, strFilename);
			m_list.AddItem(i, 0, strFilename);
			// add size
			OFSTRUCT os;
			HANDLE hFile = (HANDLE)::OpenFile(::CT2A(strFilePath), &os, OF_READ);
			BY_HANDLE_FILE_INFORMATION fileinfo;
			::GetFileInformationByHandle(hFile, &fileinfo);
			TCHAR szSize[20];
			_stprintf_s(szSize, _T("%d KB"), fileinfo.nFileSizeLow / 1024);
			m_list.AddItem(i, 1, szSize);
			// add creation time
			SYSTEMTIME st;
			FileTimeToSystemTime(&fileinfo.ftCreationTime, &st);
			TCHAR szCreationTime[24];
			_stprintf_s(szCreationTime, _T("%d/%02d/%02d %02d:%02d"), st.wYear, st.wMonth, st.wDay, (st.wHour + 8) % 24, st.wMinute);
			m_list.AddItem(i, 2, szCreationTime);
			i++;
			m_fileList.GetNext(pos);
		}
	}
};
更多详细信息请查看java教程网 http://www.itchm.com/forum-59-1.html
分享到:
评论

相关推荐

    PicSi安装程序

    内涵图制作工具,将一个jpg文件和被内涵的文件拖拽进窗口,一键生产内涵图。

    发卡系统源码无授权版 带十多套模板

    发卡系统源码无授权版 带十多套模板

    STM32F103系列PWM输出应用之纸短情长音乐——无源蜂鸣器.rar

    STM32F103系列PWM输出应用之纸短情长音乐——无源蜂鸣器

    基于matlab开发的rvm回归预测 RVM采取是与支持向量机相同的函数形式稀疏概率模型,对未知函数进行预测或分类.rar

    基于matlab开发的rvm回归预测 RVM采取是与支持向量机相同的函数形式稀疏概率模型,对未知函数进行预测或分类.rar

    STM32 CubeMX FreeRtos系统 基于lwRB通用环形缓冲区的串口非阻塞发送

    STM32工具 CubeMX 使用FreeRtos系统 基于lwRB通用环形缓冲区的串口非阻塞发送,程序使用printf,通过重定向fputc函数,将发送数据保存在FIFO中,可以在中断中调用printf,保证了系统的线程安全和中断安全,将发送任务放在线程中。LwRB有两个指针一个r读指,一个w写指针,底层采用原子操作,不需要用到锁,保证了线程安全,最大的好处是它是支持DMA的,为CPU减负。

    整站程序EasyJF官网全站源码-easyjfcom-src.rar

    EasyJF官网全站源码_easyjfcom_src.rar是一个针对计算机专业的JSP源码资料包,它包含了丰富的内容和功能,旨在帮助开发人员快速构建和管理网站。这个源码包基于Java技术栈,使用JSP(JavaServer Pages)作为前端页面渲染技术,结合了Servlet、JavaBean等后端组件,为开发者提供了一个稳定、高效的开发环境。通过使用这个源码包,开发者可以快速搭建一个具有基本功能的网站建设平台。它提供了用户注册、登录、权限管理等基本功能,同时也支持文章发布、分类管理、评论互动等常见内容管理操作。此外,源码包还包含了一些实用的辅助工具,如文件上传、数据导出等,方便开发者进行网站的维护和管理。在界面设计方面,EasyJF官网全站源码采用了简洁、易用的设计风格,使得用户可以轻松上手并进行个性化定制。同时,它还提供了一些可扩展的插件和模板,开发者可以根据自己的需求进行修改和扩展,实现更多的功能和效果。总之,EasyJF官网全站源码_easyjfcom_src.rar是一个功能强大、易于使用的计算机专业JSP源码资料包,适用于各类网站建设项目。无论是初学者还是有经验的开发者

    node-v11.13.0-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v12.10.0-win-x86.zip

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v10.2.1-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于matlab实现此压缩包包含语音信号处理中的语音变声代码加音频.rar

    基于matlab实现此压缩包包含语音信号处理中的语音变声代码加音频.rar

    node-v6.10.2.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Java 中将 UUID 存储为 Base64 字符串

    使用 Base64 编码来对 UUID(Universally Unique Identifiers) 存储在一些特定的场合被广泛的使用。使用 Base64 对比直接使用 UUID 进行存储来说能够更多的节约空间。 本文对这方面的相关内容和问题进行探讨。 在这里,使用 Base64 来对 UUID 进行存储,涉及到一些类型的转换的。Base64 是编码算法,在实际使用的时候我们更多会用到 Byte 数组的方式来进行编码的。这样我们就比较明确在对其进行 Base64 转换之前,我们应该要先干什么了。

    Java网络爬虫(蜘蛛)源码.zip

    Java网络爬虫(蜘蛛)源码.zip

    pandas数据分析学习

    这是Pandas基础学习

    毕业设计基于STM32的桌面电子时钟的设计与实现硬件端系统源码.zip

    架构 主微控制器采用 STM32F103C8T6。 目前外设部分包括: 显示模块:0.96寸4针IIC通信协议的OLED模块 温湿度采集模块:DHT11 网络通信模块:ESP8266 报警模块:高电平触发的有缘蜂鸣器 其他:若干LED灯珠以及若干贴片按键 硬件端系统使用C语言编写

    新版PHP无陌然在线云加密平台系统源码 带安装说明.rar

    新版PHP无陌然在线云加密平台系统源码 带安装说明.rar新版PHP无陌然在线云加密平台系统源码 带安装说明.rar

    记账管理系统的设计与实现

    近年来由于生活节奏的加快,好像每个人都被很多难以启齿的问题困惑,然而关于随意消费是大多数人头疼的问题,没有任何计划和筹备的情况下随意消费,导致现实生活中我们所称为的“月光族”。 当你逐渐了解自己的财务状况,就可以学着做简单的收支规划。大部分月光族的根源其实是缺乏规划,想买什么的时候就买了。并不是说规划不能随意买东西,规划的价值在于让你使用资金的效率最高。无论你用金钱换取的必需品,满足感或者快乐,都可以通过规划获得比较高的效率。 本记账系统是一个基于国内外电子商务网站的发展现状,采用B2C(Business to Consumers)模式开发的电子商务平台,它的价值所在对于那些随意消费性的人群能起到一个很大的警示作用,而且系统扩张性很强,能根据客户的不同需求进行快速改进。该系统采用B/S三层结构,服务器是Tomcat同时运用JSp技术进行动态页面设计,后台数据库是Oracle。

    最新微信文章编辑器排版工具程序源码.rar

    最新微信文章编辑器排版工具程序源码.rar最新微信文章编辑器排版工具程序源码.rar最新微信文章编辑器排版工具程序源码.rar

    249ssm-mysql-jsp 疫情冷链追溯系统.zip(可运行源码+数据库文件+文档)

    前台方面(经营者用户): 系统首页:是用这户端的系统首页,首页的最上方有投诉建议、进入后台等选项,页面下方可以根据商品编号进行商品状态的实时查询,十分方便快捷。 投诉建议:用户可以在这个系统的这个板块给系统开发者留言,向开发者反应系统使用者的疑难问题,并提出自己相应的改进建议。 商品入库:生鲜商品经营者可以在商品入库界面,对一定数量的生鲜商品进行入库操作,确保库房内的每一件商品都能追根溯源,保障产品质量安全。 商品出库:用户在商品出库界面,可以对指定的商品进行出库操作,输入出库数量,点击提交即可。 商品列表:用户还可以在商品列表的界面中,对自己旗下生鲜商品的入库、出库情况进行实时查看。 后台方面(管理者用户): 商品管理:商品管理是系统后台的核心功能,在这个功能模块中,系统管理员可以对平台内生鲜商品的出入库指令进行严格的审核,并且可以对商品的归属地追根溯源。 经营者管理:拥有最高管理权限的系统管理员,可以连接到数据库,对经营者类别、名称、经营许可证编号等基础信息进行审核。 投诉建议管理:管理员还可以对所有注册用户的投诉建议,进行删除或者回复操作,通过这种方式,与注册用户进行线上交流。

Global site tag (gtag.js) - Google Analytics