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

《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安装程序

    《PicSi安装程序:轻松创建内涵图的利器》 内涵图,作为一种独特的网络表达方式,以其独特的幽默感和丰富的信息量深受网友喜爱。而PicSi安装程序正是一款专为制作内涵图而设计的免费工具,它让普通用户也能轻松地将...

    2021-2025年中国辅助生殖行业新产品进入市场策略研究报告.pdf

    近年来,随着科技的快速发展,辅助生殖技术已经从最初的第一代试管婴儿技术(IVF-ET),发展到现在的第四代,其中包括了单精子注射技术(ICSI)、胚胎移植技术、卵子胞浆内单精子注射技术(PICSI)等。其中,第四代...

    基于ssm的网络教学平台(有报告)。Javaee项目,ssm项目。

    重点:所有项目均附赠详尽的SQL文件,这一细节的处理,让我们的项目相比其他博主的作品,严谨性提升了不止一个量级!更重要的是,所有项目源码均经过我亲自的严格测试与验证,确保能够无障碍地正常运行。 1.项目适用场景:本项目特别适用于计算机领域的毕业设计课题、课程作业等场合。对于计算机科学与技术等相关专业的学生而言,这些项目无疑是一个绝佳的选择,既能满足学术要求,又能锻炼实际操作能力。 2.超值福利:所有定价为9.9元的项目,均包含完整的SQL文件。如需远程部署可随时联系我,我将竭诚为您提供满意的服务。在此,也想对一直以来支持我的朋友们表示由衷的感谢,你们的支持是我不断前行的动力! 3.求关注:如果觉得我的项目对你有帮助,请别忘了点个关注哦!你的支持对我意义重大,也是我持续分享优质资源的动力源泉。再次感谢大家的支持与厚爱! 4.资源详情:https://blog.csdn.net/2301_78888169/article/details/144929660 更多关于项目的详细信息与精彩内容,请访问我的CSDN博客!

    2024年AI代码平台及产品发展简报-V11.pdf

    2024年AI代码平台及产品发展简报-V11

    蓝桥杯JAVA代码.zip

    蓝桥杯算法学习冲刺(主要以题目为主)

    QPSK调制解调技术研究与FPGA实现:详细实验文档的探索与实践,基于FPGA实现的QPSK调制解调技术:实验文档详细解读与验证,QPSK调制解调 FPGA设计,有详细实验文档 ,QPSK调制解调;

    QPSK调制解调技术研究与FPGA实现:详细实验文档的探索与实践,基于FPGA实现的QPSK调制解调技术:实验文档详细解读与验证,QPSK调制解调 FPGA设计,有详细实验文档 ,QPSK调制解调; FPGA设计; 详细实验文档,基于QPSK调制的FPGA设计与实验文档

    PID、ADRC和MPC轨迹跟踪控制器在Matlab 2018与Carsim 8中的Simulink仿真研究,PID、ADRC与MPC轨迹跟踪控制器在Matlab 2018与Carsim 8中的仿真研

    PID、ADRC和MPC轨迹跟踪控制器在Matlab 2018与Carsim 8中的Simulink仿真研究,PID、ADRC与MPC轨迹跟踪控制器在Matlab 2018与Carsim 8中的仿真研究,PID, ADRC和MPC轨迹跟踪控制器Simulink仿真模型。 MPC用于跟踪轨迹 ADRC用于跟踪理想横摆角 PID用于跟踪轨迹 轨迹工况有双移线,避障轨迹,正弦轨迹多种 matlab版本为2018,carsim版本为8 ,PID; ADRC; MPC; 轨迹跟踪控制器; Simulink仿真模型; 双移线; 避障轨迹; 正弦轨迹; MATLAB 2018; CarSim 8,基于Simulink的PID、ADRC与MPC轨迹跟踪控制器仿真模型研究

    基于Springboot的个性化图书推荐系统。Javaee项目,springboot项目。

    重点:所有项目均附赠详尽的SQL文件,这一细节的处理,让我们的项目相比其他博主的作品,严谨性提升了不止一个量级!更重要的是,所有项目源码均经过我亲自的严格测试与验证,确保能够无障碍地正常运行。 1.项目适用场景:本项目特别适用于计算机领域的毕业设计课题、课程作业等场合。对于计算机科学与技术等相关专业的学生而言,这些项目无疑是一个绝佳的选择,既能满足学术要求,又能锻炼实际操作能力。 2.超值福利:所有定价为9.9元的项目,均包含完整的SQL文件。如需远程部署可随时联系我,我将竭诚为您提供满意的服务。在此,也想对一直以来支持我的朋友们表示由衷的感谢,你们的支持是我不断前行的动力! 3.求关注:如果觉得我的项目对你有帮助,请别忘了点个关注哦!你的支持对我意义重大,也是我持续分享优质资源的动力源泉。再次感谢大家的支持与厚爱! 4.资源详情:https://blog.csdn.net/2301_78888169/article/details/144486173 更多关于项目的详细信息与精彩内容,请访问我的CSDN博客!

    Matlab实现Transformer-Adaboost时间序列预测的详细项目实例(含完整的程序,GUI设计和代码详解)

    内容概要:本文档详细介绍了一个利用Matlab实现Transformer-Adaboost结合的时间序列预测项目实例。项目涵盖Transformer架构的时间序列特征提取与建模,Adaboost集成方法用于增强预测性能,以及详细的模型设计思路、训练、评估过程和最终的GUI可视化。整个项目强调数据预处理、窗口化操作、模型训练及其优化(包括正则化、早停等手段)、模型融合策略和技术部署,如GPU加速等,并展示了通过多个评估指标衡量预测效果。此外,还提出了未来的改进建议和发展方向,涵盖了多层次集成学习、智能决策支持、自动化超参数调整等多个方面。最后部分阐述了在金融预测、销售数据预测等领域中的广泛应用可能性。 适合人群:具有一定编程经验的研发人员,尤其对时间序列预测感兴趣的研究者和技术从业者。 使用场景及目标:该项目适用于需要进行高质量时间序列预测的企业或机构,比如金融机构、能源供应商和服务商、电子商务公司。目标包括但不限于金融市场的波动性预测、电力负荷预估和库存管理。该系统可以部署到各类平台,如Linux服务器集群或云计算环境,为用户提供实时准确的预测服务,并支持扩展以满足更高频率的数据吞吐量需求。 其他说明:此文档不仅包含了丰富的理论分析,还有大量实用的操作指南,从项目构思到具体的代码片段都有详细记录,使用户能够轻松复制并改进这一时间序列预测方案。文中提供的完整代码和详细的注释有助于加速学习进程,并激发更多创新想法。

    液滴穿越障碍:从文献到案例的复现研究,液滴破裂与障碍物穿越:文献复现案例研究,液滴生成并通过障碍物破裂 该案例是文献复现,文献与案例一起 ,液滴生成; 障碍物破裂; 文献复现; 案例研究,液滴破

    液滴穿越障碍:从文献到案例的复现研究,液滴破裂与障碍物穿越:文献复现案例研究,液滴生成并通过障碍物破裂。 该案例是文献复现,文献与案例一起。 ,液滴生成; 障碍物破裂; 文献复现; 案例研究,液滴破裂:障碍挑战的文献复现案例

    蓝桥杯练习题_2.zip

    蓝桥杯算法学习冲刺(主要以题目为主)

    蓝桥杯笔记,用于个人学习进步.zip

    蓝桥杯算法学习冲刺(主要以题目为主)

    基于最小递归二乘法的MPC自适应轨迹跟踪控制优化 针对轮胎刚度时变特性提升模型精度与鲁棒性,仿真验证满足车辆低速高精度跟踪与高速稳定性提升 ,基于变预测时域MPC自适应轨迹跟踪控制与轮胎侧偏刚度优化提

    基于最小递归二乘法的MPC自适应轨迹跟踪控制优化 针对轮胎刚度时变特性提升模型精度与鲁棒性,仿真验证满足车辆低速高精度跟踪与高速稳定性提升。,基于变预测时域MPC自适应轨迹跟踪控制与轮胎侧偏刚度优化提升模型精度和鲁棒性,基于变预测时域的MPC自适应轨迹跟踪控制,针对轮胎刚度时变的特点造成控制模型精度降低,基于最小递归二乘法(RLS)估算的轮胎侧偏刚度,提升了模型的控制精度和鲁棒性,通过carsim与simulink联合仿真结果发现,改进后的轨迹跟踪控制器既满足了车辆低速行驶下的轨 迹跟踪精度,也一定程度上克服了高速下车辆容易失去稳定性的问题。 有详细的lunwen分析说明和资料,以及本人的,仿真包运行。 ,基于变预测时域的MPC; 自适应轨迹跟踪控制; 轮胎刚度时变; 控制模型精度降低; 最小递归二乘法(RLS)估算; 模型控制精度和鲁棒性提升; carsim与simulink联合仿真; 轨迹跟踪控制器; 车辆稳定性。,基于变预测时域MPC的轮胎刚度自适应轨迹跟踪控制策略研究

    GMSK调制解调技术研究:基于FPGA设计与实验详解,GMSK调制解调技术详解:基于FPGA设计的实验文档与实践应用,GMSK调制解调 FPGA设计,有详细实验文档 ,GMSK调制解调; FPGA设计

    GMSK调制解调技术研究:基于FPGA设计与实验详解,GMSK调制解调技术详解:基于FPGA设计的实验文档与实践应用,GMSK调制解调 FPGA设计,有详细实验文档 ,GMSK调制解调; FPGA设计; 详细实验文档; 实验结果分析,GMSK调制解调技术:FPGA设计与实验详解

    (源码)基于Arduino和Python的Cansat卫星系统.zip

    # 基于Arduino和Python的Cansat卫星系统 ## 项目简介 本项目是一个Cansat卫星系统,旨在设计和实现一个小型卫星模型,通过火箭发射至1公里高空,并使用地面站接收其传输的数据。项目涉及Arduino编程、Python数据处理和可视化。 ## 主要特性和功能 1. 硬件组件 使用Arduino Nano作为Cansat的微控制器。 搭载BMP 280温度和压力传感器、ATGM336H GPS模块、LoRa通信模块等。 地面站使用Arduino Uno和LoRa通信模块接收数据。 2. 数据处理 使用Python进行数据处理和可视化,包括数据清洗、计算风速、绘制温度、压力、风速和海拔随时间变化的图表等。 3. 通信与控制 通过LoRa模块实现Cansat与地面站之间的数据传输。 提供实时监视和记录数据的脚本。 ## 安装和使用步骤 ### 1. 硬件准备

    LongSung-USB-Drivers-V2.0-for-Windows

    U9300C 龙尚4G模块安装后模块才能正常使用,win7 win10驱动程序,支持USB转接板。

    (源码)基于Arduino平台的物联网温湿度监控系统.zip

    # 基于Arduino平台的物联网温湿度监控系统 ## 项目简介 这是一个基于Arduino平台的物联网温湿度监控项目,旨在通过简单的硬件设备实现环境数据的实时监测与远程管理。该项目适用于智能家居、农业种植等领域。 ## 项目的主要特性和功能 1. 温湿度数据采集通过Arduino板连接温湿度传感器,实时采集环境数据。 2. 数据传输将采集到的数据通过无线网络模块发送到服务器或远程终端。 3. 数据可视化可在电脑或移动设备端展示实时的温湿度数据。 4. 报警功能当温湿度数据超过预设阈值时,自动触发报警通知。 ## 安装使用步骤 前提假设用户已经下载了本项目的源码文件。以下是简单明了的安装使用步骤 1. 环境准备安装Arduino开发环境,配置必要的硬件接口。 2. 硬件连接将Arduino板与温湿度传感器、无线网络模块连接。 3. 代码上传将本项目提供的Arduino代码上传至Arduino板。

    基于需求响应与清洁能源接入的配电网重构优化:综合成本与混合整数凸规划模型分析(matlab实现),基于需求响应与清洁能源接入的配电网重构算法研究:网损与成本优化的仿真分析,高比例清洁能源接入下计及需求

    基于需求响应与清洁能源接入的配电网重构优化:综合成本与混合整数凸规划模型分析(matlab实现),基于需求响应与清洁能源接入的配电网重构算法研究:网损与成本优化的仿真分析,高比例清洁能源接入下计及需求响应的配电网重构(matlab代码) 该程序复现《高比例清洁能源接入下计及需求响应的配电网重构》,以考虑网损成本、弃风弃光成本和开关操作惩罚成本的综合成本最小为目标,针对配电网重构模型的非凸性,引入中间变量并对其进行二阶锥松弛,构建混合整数凸规划模型,采用改进的 IEEE33 节点配电网进行算例仿真,分析了需求响应措施和清洁能源渗透率对配电网重构结果的影响。 该程序复现效果和出图较好(详见程序结果部分),注释清楚,方便学习 ,高比例清洁能源; 需求响应; 配电网重构; 二阶锥松弛; 综合成本最小化; MATLAB代码; IEEE33节点配电网; 复现效果; 出图; 注释清楚。,Matlab代码复现:高比例清洁能源接入下的配电网重构模型与需求响应分析

    (源码)基于C++的RapidJSON库测试项目.zip

    # 基于C++的RapidJSON库测试项目 ## 项目简介 本项目是一个基于C++的RapidJSON库测试项目,主要用于测试RapidJSON库的功能正确性、性能以及稳定性。RapidJSON是一个高效的C++ JSON解析生成库,广泛应用于各种场景。本项目通过编写一系列的单元测试,覆盖了RapidJSON库的主要功能点,包括JSON解析、生成、内存管理、编码转换等,以确保RapidJSON库在各种情况下都能正确、稳定地工作。 ## 项目的主要特性和功能 1. 单元测试框架使用Google Test测试框架进行单元测试,确保测试的可靠性和可扩展性。 2. 全面测试覆盖覆盖了RapidJSON库的主要功能点,包括JSON解析、生成、内存管理、编码转换等,以及针对各种输入数据的测试。 3. 性能测试通过性能基准测试,评估RapidJSON库在处理不同规模和类型的JSON数据时的性能表现。

    蓝桥杯单片机十一届试题.zip

    蓝桥杯算法学习冲刺(主要以题目为主)

Global site tag (gtag.js) - Google Analytics