主要界面如下:

主要代码如下:

 BOOL CPEParseDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码
InitSectionList(); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void CPEParseDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CPEParseDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} void CPEParseDlg::OnBnClickedButtonLook()
{
// TODO: 在此添加控件通知处理程序代码
((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->GetWindowText(m_strPathName);
m_strPathName = m_strPathName.Trim();
if (m_strPathName.IsEmpty())
{
AfxMessageBox(_T("请选择要查看的文件!"));
return;
} FileCreate();
if (FALSE == IsPeFileAndGetPePointer())
{
AfxMessageBox(_T("该文件不是PE文件!"));
return;
}
ParseBasePe();
EnumSections();
} void CPEParseDlg::OnBnClickedButtonExit()
{
// TODO: 在此添加控件通知处理程序代码
OnOK();
} void CPEParseDlg::OnBnClickedButtonBrowse()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog FileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, _T("Executeable Files (*.exe)|*.exe|Dynamic Linker Library Files (*.dll)|*.dll|OCX Files (*.ocx)|*.ocx|Driver Files (*.sys)|*.sys||"));
FileDlg.DoModal();
CString strPathName = FileDlg.GetPathName();
((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->SetWindowText(strPathName);
} BOOL CPEParseDlg::FileCreate(void)
{
BOOL bRet = FALSE; m_hFile = CreateFile(m_strPathName.GetBuffer(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == m_hFile)
{
return bRet;
} m_hMap = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, , , NULL);
if (NULL == m_hMap)
{
CloseHandle(m_hFile);
return bRet;
} m_lpBase = MapViewOfFile(m_hMap, FILE_MAP_READ | FILE_MAP_WRITE, , , );
if (NULL == m_lpBase)
{
CloseHandle(m_hMap);
CloseHandle(m_hFile);
return bRet;
} bRet = TRUE;
return bRet;
} void CPEParseDlg::InitSectionList(void)
{
CRect Rect;
m_ctrlSections.GetClientRect(&Rect);
m_ctrlSections.SetExtendedStyle(m_ctrlSections.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_ctrlSections.InsertColumn(, _T("节名"));
m_ctrlSections.InsertColumn(, _T("V.偏移"));
m_ctrlSections.InsertColumn(, _T("V.大小"));
m_ctrlSections.InsertColumn(, _T("R.偏移"));
m_ctrlSections.InsertColumn(, _T("R.大小"));
m_ctrlSections.InsertColumn(, _T("标志"));
m_ctrlSections.SetColumnWidth(, Rect.Width() / );
m_ctrlSections.SetColumnWidth(, Rect.Width() / );
m_ctrlSections.SetColumnWidth(, Rect.Width() / );
m_ctrlSections.SetColumnWidth(, Rect.Width() / );
m_ctrlSections.SetColumnWidth(, Rect.Width() / );
m_ctrlSections.SetColumnWidth(, Rect.Width() / );
} BOOL CPEParseDlg::IsPeFileAndGetPePointer(void)
{
BOOL bRet = FALSE; m_pDosHeader = (PIMAGE_DOS_HEADER)m_lpBase;
if (IMAGE_DOS_SIGNATURE != m_pDosHeader->e_magic)
{
return bRet;
} m_pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)m_lpBase + m_pDosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != m_pNtHeaders->Signature)
{
return bRet;
} m_pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)&(m_pNtHeaders->OptionalHeader) + m_pNtHeaders->FileHeader.SizeOfOptionalHeader); bRet = TRUE;
return bRet;
} void CPEParseDlg::ParseBasePe(void)
{
m_strEntryPoint.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.AddressOfEntryPoint);
m_strImageBase.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.ImageBase);
m_strLinkerVersion.Format(_T("%d.%d"), m_pNtHeaders->OptionalHeader.MajorLinkerVersion, m_pNtHeaders->OptionalHeader.MinorLinkerVersion);
m_strSectionNum.Format(_T("%02X"), m_pNtHeaders->FileHeader.NumberOfSections);
m_strFileAlignment.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.FileAlignment);
m_strSectionAlignment.Format(_T("%08X"), m_pNtHeaders->OptionalHeader.SectionAlignment);
UpdateData(FALSE);
} void CPEParseDlg::EnumSections(void)
{
m_ctrlSections.DeleteAllItems(); CString strTemp;
int iSectionNumber = m_pNtHeaders->FileHeader.NumberOfSections; for (int i = ; i < iSectionNumber; ++i)
{
strTemp = m_pSectionHeader[i].Name;
m_ctrlSections.InsertItem(i, strTemp); strTemp.Format(_T("%08X"), m_pSectionHeader[i].VirtualAddress);
m_ctrlSections.SetItemText(i, , strTemp); strTemp.Format(_T("%08X"), m_pSectionHeader[i].Misc.VirtualSize);
m_ctrlSections.SetItemText(i, , strTemp); strTemp.Format(_T("%08X"), m_pSectionHeader[i].PointerToRawData);
m_ctrlSections.SetItemText(i, , strTemp); strTemp.Format(_T("%08X"), m_pSectionHeader[i].SizeOfRawData);
m_ctrlSections.SetItemText(i, , strTemp); strTemp.Format(_T("%08X"), m_pSectionHeader[i].Characteristics);
m_ctrlSections.SetItemText(i, , strTemp);
}
} void CPEParseDlg::OnBnClickedRadioVa()
{
// TODO: 在此添加控件通知处理程序代码
m_nSelected = ;
((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetReadOnly(FALSE);
((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetReadOnly(TRUE);
((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetReadOnly(TRUE);
} void CPEParseDlg::OnBnClickedRadioRva()
{
// TODO: 在此添加控件通知处理程序代码
m_nSelected = ;
((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetReadOnly(TRUE);
((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetReadOnly(FALSE);
((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetReadOnly(TRUE);
} void CPEParseDlg::OnBnClickedRadioFileoffset()
{
// TODO: 在此添加控件通知处理程序代码
m_nSelected = ;
((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetWindowText(_T(""));
((CEdit*)GetDlgItem(IDC_EDIT_VA))->SetReadOnly(TRUE);
((CEdit*)GetDlgItem(IDC_EDIT_RVA))->SetReadOnly(TRUE);
((CEdit*)GetDlgItem(IDC_EDIT_FILEOFFSET))->SetReadOnly(FALSE);
} void CPEParseDlg::OnBnClickedButtonCalc()
{
// TODO: 在此添加控件通知处理程序代码
m_strImageBase = m_strImageBase.Trim();
if (m_strImageBase.IsEmpty())
{
AfxMessageBox(_T("请先点击查看按钮!"));
return;
} CString strPathName;
((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->GetWindowText(strPathName);
if (strPathName != m_strPathName)
{
AfxMessageBox(_T("你已经更换了PE文件,请先点击查看按钮!"));
return;
} DWORD dwAddr = ;
dwAddr = GetAddr();
int nInNum = GetAddrInSectionNum(dwAddr);
CalcAddr(nInNum, dwAddr);
} DWORD CPEParseDlg::GetAddr(void)
{
TCHAR szAddr[] = {};
DWORD dwAddr = ;
switch (m_nSelected)
{
case :
GetDlgItemText(IDC_EDIT_VA, szAddr, );
HexStrToInt(szAddr, &dwAddr);
break;
case :
GetDlgItemText(IDC_EDIT_RVA, szAddr, );
HexStrToInt(szAddr, &dwAddr);
break;
case :
GetDlgItemText(IDC_EDIT_FILEOFFSET, szAddr, );
HexStrToInt(szAddr, &dwAddr);
break;
} return dwAddr;
} int CPEParseDlg::GetAddrInSectionNum(DWORD dwAddr)
{
int nInNum = ;
int nSectionNum = m_pNtHeaders->FileHeader.NumberOfSections;
switch (m_nSelected)
{
case :
{
DWORD dwImageBase = m_pNtHeaders->OptionalHeader.ImageBase;
for (nInNum = ; nInNum < nSectionNum; nInNum++)
{
if (dwAddr >= dwImageBase + m_pSectionHeader[nInNum].VirtualAddress
&& dwAddr <= dwImageBase + m_pSectionHeader[nInNum].VirtualAddress
+ m_pSectionHeader[nInNum].Misc.VirtualSize)
{
return nInNum;
}
}
break;
}
case :
for (nInNum = ; nInNum < nSectionNum; nInNum++)
{
if (dwAddr >= m_pSectionHeader[nInNum].VirtualAddress
&& dwAddr <= m_pSectionHeader[nInNum].VirtualAddress
+ m_pSectionHeader[nInNum].Misc.VirtualSize)
{
return nInNum;
}
}
break;
case :
for (nInNum = ; nInNum < nSectionNum; nInNum++)
{
if (dwAddr >= m_pSectionHeader[nInNum].PointerToRawData
&& dwAddr <= m_pSectionHeader[nInNum].PointerToRawData
+ m_pSectionHeader[nInNum].SizeOfRawData)
{
return nInNum;
}
}
break;
} return -;
} void CPEParseDlg::CalcAddr(int nInNum, DWORD dwAddr)
{
DWORD dwVa = ;
DWORD dwRva = ;
DWORD dwFileOffset = ; switch (m_nSelected)
{
case :
dwVa = dwAddr;
dwRva = dwVa - m_pNtHeaders->OptionalHeader.ImageBase;
dwFileOffset = m_pSectionHeader[nInNum].PointerToRawData + (dwRva - m_pSectionHeader[nInNum].VirtualAddress);
break;
case :
dwVa = dwAddr + m_pNtHeaders->OptionalHeader.ImageBase;
dwRva = dwAddr;
dwFileOffset = m_pSectionHeader[nInNum].PointerToRawData + (dwRva - m_pSectionHeader[nInNum].VirtualAddress);
break;
case :
dwFileOffset = dwAddr;
dwRva = m_pSectionHeader[nInNum].VirtualAddress + (dwFileOffset - m_pSectionHeader[nInNum].PointerToRawData);
dwVa = dwRva + m_pNtHeaders->OptionalHeader.ImageBase;
break;
} SetDlgItemText(IDC_EDIT_SECTION, CString(m_pSectionHeader[nInNum].Name)); CString str;
str.Format(_T("%08X"), dwVa);
SetDlgItemText(IDC_EDIT_VA, str); str.Format(_T("%08X"), dwRva);
SetDlgItemText(IDC_EDIT_RVA, str); str.Format(_T("%08X"), dwFileOffset);
SetDlgItemText(IDC_EDIT_FILEOFFSET, str);
} void CPEParseDlg::HexStrToInt(TCHAR* szAddr, DWORD* pdwAddr)
{
int iLen = lstrlen(szAddr);
*pdwAddr = ; for (int i = ; i < iLen; i++)
{
if (szAddr[i] >= _T('') && szAddr[i] <= _T(''))
{
*pdwAddr = ((*pdwAddr) << ) | (szAddr[i] - _T(''));
}
else if (szAddr[i] >= _T('A') && szAddr[i] <= _T('F'))
{
*pdwAddr = ((*pdwAddr) << ) | (szAddr[i] - _T('A') + 0xA);
}
else if (szAddr[i] >= _T('a') && szAddr[i] <= _T('f'))
{
*pdwAddr = ((*pdwAddr) << ) | (szAddr[i] - _T('a') + 0xA);
}
}
} void CPEParseDlg::OnDestroy()
{
CDialog::OnDestroy(); // TODO: 在此处添加消息处理程序代码
if (NULL != m_lpBase)
{
UnmapViewOfFile(m_lpBase);
} if (NULL != m_hMap)
{
CloseHandle(m_hMap);
} if (INVALID_HANDLE_VALUE != m_hFile)
{
CloseHandle(m_hFile);
}
} HBRUSH CPEParseDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: 在此更改 DC 的任何属性
//if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC || nCtlColor == CTLCOLOR_EDIT)
//{
// pDC->SetBkMode(TRANSPARENT);
// return CreateSolidBrush(RGB(0x2F, 0x4F, 0x4F));
//} // TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
} void CPEParseDlg::OnBnClickedButtonAddsection()
{
// TODO: 在此添加控件通知处理程序代码
m_strImageBase = m_strImageBase.Trim();
if (m_strImageBase.IsEmpty())
{
AfxMessageBox(_T("请先点击查看按钮!"));
return;
} CString strPathName;
((CEdit*)GetDlgItem(IDC_EDIT_FILEPATH))->GetWindowText(strPathName);
if (strPathName != m_strPathName)
{
AfxMessageBox(_T("你已经更换了PE文件,请先点击查看按钮!"));
return;
} TCHAR szSectionName[] = {};
int nSectionSize = ; GetDlgItemText(IDC_EDIT_SECTIONNAME, szSectionName, );
nSectionSize = GetDlgItemInt(IDC_EDIT_SECTIONSIZE, FALSE, TRUE); AddSection(szSectionName, nSectionSize);
} void CPEParseDlg::AddSection(TCHAR* szSectionName, int nSectionSize)
{
int nSectionNum = m_pNtHeaders->FileHeader.NumberOfSections;
DWORD dwFileAlignment = m_pNtHeaders->OptionalHeader.FileAlignment;
DWORD dwSectionAlignment = m_pNtHeaders->OptionalHeader.SectionAlignment; PIMAGE_SECTION_HEADER pTempSection = m_pSectionHeader + nSectionNum; int nLen = WideCharToMultiByte(CP_ACP, , (LPCWSTR)szSectionName, -, NULL, , NULL, NULL);
char *pszSectionNameA = new char[nLen];
WideCharToMultiByte(CP_ACP, , szSectionName, -, pszSectionNameA, nLen * sizeof(char), NULL, NULL);
//拷贝节名
strncpy((char*)(pTempSection->Name), pszSectionNameA, );
delete[] pszSectionNameA;
pszSectionNameA = NULL;
//节的内存大小
pTempSection->Misc.VirtualSize = AlignSize(nSectionSize, dwSectionAlignment);
//节的内存起始位置
pTempSection->VirtualAddress = m_pSectionHeader[nSectionNum - ].VirtualAddress
+ AlignSize(m_pSectionHeader[nSectionNum - ].Misc.VirtualSize, dwSectionAlignment);
//节的文件大小
pTempSection->SizeOfRawData = AlignSize(nSectionSize, dwFileAlignment);
//节的文件起始位置
pTempSection->PointerToRawData = m_pSectionHeader[nSectionNum - ].PointerToRawData
+ AlignSize(m_pSectionHeader[nSectionNum - ].SizeOfRawData, dwFileAlignment);
//修正节数量
m_pNtHeaders->FileHeader.NumberOfSections++;
//修正映像大小
m_pNtHeaders->OptionalHeader.SizeOfImage += pTempSection->Misc.VirtualSize;
//填充内存映射
FlushViewOfFile(m_lpBase, );
//添加节数据
AddSectionData(pTempSection->SizeOfRawData); CString str;
str.Format(_T("%02X"), m_pNtHeaders->FileHeader.NumberOfSections);
((CEdit*)GetDlgItem(IDC_EDIT_SECTIONNUM))->SetWindowText(str);
EnumSections();
} DWORD CPEParseDlg::AlignSize(int nSectionSize, DWORD dwAlignment)
{
int nSize = nSectionSize;
if (nSize % dwAlignment != )
{
nSectionSize = (nSize / dwAlignment + ) * dwAlignment;
} return nSectionSize;
} void CPEParseDlg::AddSectionData(int nSectionSize)
{
PBYTE pByte = NULL;
pByte = (PBYTE)malloc(nSectionSize);
ZeroMemory(pByte, nSectionSize); DWORD dwNum = ;
SetFilePointer(m_hFile, , , FILE_END);
WriteFile(m_hFile, pByte, nSectionSize, &dwNum, NULL);
FlushFileBuffers(m_hFile); free(pByte);
}

下载地址如下:

http://pan.baidu.com/s/1hqBR06S

PE查看器的更多相关文章

  1. 用Qt写软件系列一:QCacheViewer(浏览器缓存查看器)

    介绍 Cache技术广泛应用于计算机行业的软硬件领域.该技术既是人们对新技术探讨的结果,也是对当前软硬件计算能力的一种妥协.在浏览器中使用cache技术,可以大幅度提高web页面的响应速度,降低数据传 ...

  2. PE解析器的编写(四)——数据目录表的解析

    在PE结构中最重要的就是区块表和数据目录表,上节已经说明了如何解析区块表,下面就是数据目录表,在数据目录表中一般只关心导入表,导出表和资源这几个部分,但是资源实在是太复杂了,而且在一般的病毒木马中也不 ...

  3. Map工具系列-08-map控件查看器

    所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map ...

  4. wpf 仿QQ图片查看器

    参考博客 WPF下的仿QQ图片查看器 wpf图片查看器,支持鼠标滚动缩放拖拽 实现效果 主要参考的WPF下的仿QQ图片查看器,原博主只给出了部分代码. 没有完成的部分 1.右下角缩略图是原图不是缩略图 ...

  5. Win10系统怎样让打开图片方式为照片查看器

    转载自:百度经验 http://jingyan.baidu.com/article/5d368d1ef0cad13f60c057e3.html 1.首先,我们需要使用注册表编辑器来开启Win10系统照 ...

  6. 发布两款JQ小插件(图片查看器 + 分类选择器),开源

    图片查看器,github地址:https://github.com/VaJoy/imgViewer 效果如下: 这款当初大概写了2小时,有点匆忙地赶出来的,使用的接口很简单: $.bindViewer ...

  7. IIS事件查看器_WebServer事件查看器_帮助查看IIS-Web服务器事件执行日志

    IIS服务器是我们常用的Web站点部署工具,而我们有时可能遇到IIS服务器的应用程序池莫名其妙的关闭了,或者是其他未知原因等等,我们这是可以通过微软提供的WebServer(Web服务事件查看器),来 ...

  8. wpf图片查看器,支持鼠标滚动缩放拖拽

    最近项目需要,要用到一个图片查看器,类似于windows自带的图片查看器那样,鼠标滚动可以缩放,可以拖拽图片,于是就写了这个简单的图片查看器. 前台代码: <Window x:Class=&qu ...

  9. 在Windows 10下启用旧的照片查看器

    从Windows 10开始,默认只能通过“照片”来查看图片了,非常不方便!通过将下列文本保存在.reg文件后导入,即可找回Windows XP时代的“照片查看器”. Windows Registry ...

随机推荐

  1. Apache Thrift学习之一(入门及Java实例演示)

    目录: 概述 下载配置 基本概念 数据类型 服务端编码基本步骤 客户端编码基本步骤 数据传输协议 实例演示(java) thrift生成代码 实现接口Iface TSimpleServer服务模型 T ...

  2. mysql处理上百万条的数据库如何优化语句来提高处理查询效率

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  3. Win8驱动测试模式

    打开驱动测试模式(保存成bat文件,双击执行) bcdedit /set testsigning on pause 执行完成后,看见提示操作成功的提示,之后我们重启一下,再次进入系统,在桌面的右下角会 ...

  4. webim-界面细节调整

    1)左侧css调整 3)界面和滚动条美化 8)界面

  5. Linux 下绑定域名与IP地址

    在 Linux 下,hosts 文件的路径是 /etc/hosts,此文件需要有root权限才可编辑,条目也是通过“IP 域名”的格式将域名与IP进行绑定. 对 Linux 的 hosts 配置文件的 ...

  6. linux下分卷tar.bz文件的合并并解压缩

    linux下分卷tar.bz文件的合并并解压缩 例: linux.tar.bz2.001;linux.tar.bz2.002;linux.tar.bz2.003; 首先 cat linux.tar.b ...

  7. CRM 2016 自定义lookup过滤

    function preFilterLookup() { //终端业态 Xrm.Page.getControl("new_typeofoperationid").addPreSea ...

  8. spring listener引用spring中bean

    在SSH项目开发中,会使用到监听器Listener,并且有时需要在监听器中完成数据库的操作等动作,此时需要在Listener中使用到Spring容器中的Bean.Spring容器本身就是在web.xm ...

  9. 九度OJ1085

    说起这个题呢,就不得不提一种快速求解幂的算法——反复平方法,可以在O(logn)的复杂度完成求幂运算.具体思路我不说,巫泽俊大神翻译的<挑战程序设计竞赛>P123对此有详细描述. 但仅知道 ...

  10. 如何让Form窗体接收KeyDown事件?

    在使用.Net Framework编写窗体应用程序的时候,有时有需要响应窗体的按键消息.当窗体上没有任何其他控件的时候,窗体是可以直接响应这些消息的. 但是当窗体上有其他控件时,会发现窗体再也不会响应 ...