热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《PicSi的实现细节》第4节主窗口CMainDlg的定义及杂项

主窗口CMainDlg的定义很好理解,虽然简单但却至关重要,毕竟Creator子窗口、About子窗口都被主窗口管理,它就是PicSi的“领导”,对全局进行控制。
        主窗口CMainDlg的定义很好理解,虽然简单但却至关重要,毕竟Creator子窗口、About子窗口都被主窗口管理,它就是PicSi的“领导”,对全局进行控制。
       首先需定义3个控制成员变量m_tab、m_creator及m_about,分别对应主窗口中tab控制、Creator子窗口、About子窗口。
       接着在OnInitDialog方法中初始化Tab控制,创建Creator子窗口和About子窗口,默认情况下显示Creator子窗口而隐藏About子窗口。此外,调用方法DraAcceptFiles(TRUE),允许文件拖拽(Drag and drop)。
       定义OnSize方法,调整上述控制的位置和尺寸,比较简单,再此不赘述。
       主窗口需要响应IDC_TAB控制的通知消息TCN_SELCHANGE,当用户选择某一选项卡时,该通知消息将会被抛出。定义OnTabSelChange方法,它根据用户的选中,对Creator子窗口和About子窗口进行Show或Hide操作。主窗口还需要响应WM_DROPFILES消息,当用户将一个或多个文件拖拽到PicSi的窗口中时,该消息将会被主窗口捕获。
       在OnDropFiles方法中,首先判断拖入的是否为文件夹,若是则弹窗提示不能添加文件夹,若否则说明是常规文件,调用m_creator.AddFile方法添加到Listview控制中。
       CMainDlg的全部代码如下所示:
// MainDlg.h : interface of the CMainDlg class
//
/////////////////////////////////////////////////////////////////////////////

#pragma once

#include "private/Fcommon.h"
#include "src/PicsiCreatorDlg.h"
#include "aboutdlg.h"

class CMainDlg : public CDialogImpl, public CUpdateUI,
public CMessageFilter, public CIdleHandler
{
public:
enum { IDD = IDD_MAINDLG };

private:
CTabCtrl m_tab;
CPicsiCreatorDlg m_creator;
CAboutDlg m_about;

public:
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
return CWindow::IsDialogMessage(pMsg);
}

virtual BOOL OnIdle()
{
return FALSE;
}

BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()

BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_SIZE, OnSize)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
NOTIFY_HANDLER(IDC_TAB, TCN_SELCHANGE, OnTabSelChange)
MESSAGE_HANDLER(WM_DROPFILES, OnDropFiles)
END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// center the dialog on the screen
CenterWindow();

// set icons
HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
SetIcon(hIcon, TRUE);
HICON hIcOnSmall= AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
SetIcon(hIconSmall, FALSE);

// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);

UIAddChildWindowContainer(m_hWnd);

// init tab
m_tab.Attach(GetDlgItem(IDC_TAB));
m_tab.InsertItem(0, _T("Main"));
m_tab.InsertItem(1, _T("About"));
m_tab.SetCurSel(0);

m_creator.Create(m_hWnd);
m_creator.ShowWindow(SW_SHOW);
DragAcceptFiles(TRUE);
m_about.Create(m_hWnd);
m_about.ShowWindow(SW_HIDE);
return TRUE;
}

LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// unregister message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->RemoveMessageFilter(this);
pLoop->RemoveIdleHandler(this);

return 0;
}

LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if( wParam != SIZE_MINIMIZED ) {
int nWidth = LOWORD(lParam);
int nHeight = HIWORD(lParam);
m_tab.SetWindowPos(NULL, 4, 4, nWidth - 8, nHeight - 8, SWP_NOACTIVATE | SWP_NOZORDER);
RECT rc;
m_tab.GetClientRect(&rc);
m_tab.AdjustRect(FALSE, &rc);
POINT pt;
pt.x = rc.left;
pt.y = rc.top;
::ClientToScreen(m_tab, &pt);
ScreenToClient(&pt);
m_creator.SetWindowPos(NULL, pt.x, pt.y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
m_about.SetWindowPos(NULL, pt.x, pt.y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
DragAcceptFiles(TRUE);
}
bHandled = FALSE;
return 0;
}

LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CAboutDlg dlg;
dlg.DoModal();
return 0;
}

LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// TODO: Add validation code
CloseDialog(wID);
return 0;
}

LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CloseDialog(wID);
return 0;
}

LRESULT OnTabSelChange(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
{
int nSel = m_tab.GetCurSel();
if(nSel <0)
return 0;
// erase
m_creator.ShowWindow(SW_HIDE);
m_about.ShowWindow(SW_HIDE);
DragAcceptFiles(FALSE);
// show one
if(nSel == 0) {
m_creator.ShowWindow(SW_SHOW);
DragAcceptFiles(TRUE);
}
else
m_about.ShowWindow(SW_SHOW);
return 0;
}

LRESULT OnDropFiles(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
int nSel = m_tab.GetCurSel();
if(nSel <0)
return 0;
HDROP hDrop = (HDROP)wParam;
int nCount = ::DragQueryFile(hDrop, -1, NULL, 0);
TCHAR szFile[MAX_PATH];
BOOL bAlreadyShowTip = FALSE;
for(int i = 0; i ::DragQueryFile(hDrop, i, szFile, MAX_PATH);
if( PS_IsDirectory(szFile) && !bAlreadyShowTip ) {
PS_MessageBox(_T("You cannot add a directory, only file is allowed!"), MB_ICONWARNING);
bAlreadyShowTip = TRUE;
}
else m_creator.AddFile(szFile);
}
::DragFinish(hDrop);
return 0;
}

void CloseDialog(int nVal)
{
DestroyWindow();
::PostQuitMessage(nVal);
}
};
       程序中调用了一些以PS_为前缀的函数,它们是整个项目中的公共函数,定义在private/Fcommon.h文件中。下面简要说明这些函数的作用:
  • PS_IsDirectory - 判断路径是否为文件夹。
  • PS_DirExists - 判断文件夹是否已经存在。
  • PS_MessageBox - 弹出对话框提示。
  • PS_PathAppendBackslash - 在字符串末尾添加反斜杠。
  • PS_GetAppDataDirectory - 获得PicSi的AppData文件夹路径。
  • PS_GetInstallationDirectory - 获得PicSi可执行文件所在文件夹的路径。
  • PS_GetFilename - 从文件全路径名抽取出文件名。
  • PS_ChangeFileExtension - 修改文件的后缀名。
  • PS_AddDoubleQuotationMarks - 为字符串添加双引号。
       Fommon.h中的全部代码如下所示:
///////////////////////////////////////////////////////////////////////////////
# pragma once
///////////////////////////////////////////////////////////////////////////////

// PS_IsDirectory
inline
BOOL PS_IsDirectory(LPCTSTR szPath) throw()
{
DWORD dwCode = ::GetFileAttributes(szPath);
if( dwCode == INVALID_FILE_ATTRIBUTES )
return FALSE;
return (FILE_ATTRIBUTE_DIRECTORY & dwCode) ? TRUE : FALSE;
}

// PS_DirExists
inline
BOOL PS_DirExists(LPCTSTR szPath) throw()
{
return PS_IsDirectory(szPath);
}

// PS_MessageBox
inline
void PS_MessageBox(LPCTSTR szMessage, UINT uIcon = 0) throw()
{
AtlMessageBox(NULL, szMessage, _T("PicSi Notice"), MB_OK | uIcon);
}

// PS_PathAppendBackslash
inline
BOOL PS_PathAppendBackslash(WTL::CString& strPath) throw()
{
int nLen = strPath.GetLength() + 1;
if(nLen > MAX_PATH)
--nLen;
LPTSTR szPath = strPath.GetBuffer(nLen);
if(szPath == NULL)
return FALSE;
szPath[nLen] = _T('\0');
::PathAddBackslash(szPath);
strPath.ReleaseBuffer();
return TRUE;
}

// PS_GetAppDataDirectory
inline
BOOL PS_GetAppDataDirectory(WTL::CString& strAppDataDirectory) throw()
{
LPTSTR szPath = strAppDataDirectory.GetBufferSetLength(MAX_PATH);
if(szPath == NULL)
return FALSE;
if(!::SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, FALSE)) {
strAppDataDirectory.ReleaseBuffer();
return FALSE;
}
strAppDataDirectory.ReleaseBuffer();
return TRUE;
}

// PS_GetInstallationDirectory
inline
BOOL PS_GetInstallationDirectory(WTL::CString& strPath) throw()
{
TCHAR szPath[MAX_PATH];
if(!GetModuleFileName(NULL, szPath, MAX_PATH))
return FALSE;
strPath = szPath;
int nPos = strPath.ReverseFind(_T('\\'));
strPath = strPath.Mid(0, nPos);
return TRUE;
}

// PS_GetFilename
inline
BOOL PS_GetFilename(LPCTSTR szFullPath, WTL::CString& strFilename) throw()
{
ATLASSERT(szFullPath != NULL);
strFilename = szFullPath;
int nPos = strFilename.ReverseFind(_T('\\'));
if( nPos <0 )
return FALSE;
else
strFilename = strFilename.Mid(nPos + 1);
return TRUE;
}

// PS_ChangeFileExtension
inline
void PS_ChangeFileExtension(LPCTSTR szFilename, LPCTSTR szExt, WTL::CString& strResult) throw()
{
strResult = szFilename;
int nPos = strResult.Find(_T('.'));
if(nPos <0)
strResult += szExt;
else {
strResult = strResult.Mid(0, nPos);
strResult += szExt;
}
}

// PS_AddDoubleQuotationMarks
inline
void PS_AddDoubleQuotationMarks(WTL::CString& strPath) throw()
{
strPath += _T("\"");
strPath = _T("\"") + strPath;
}
///////////////////////////////////////////////////////////////////////////////

       结束语:《PicSi的实现细节》系列文章到这里就结束了。如果你需要PicSi的工程文档和源码,请发邮件至 umeli@live.cn 索取。

推荐阅读
author-avatar
I技男
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有