课上完了连老师见都没见一面QAQ....记录一下该小项目

效果如下:



1、实现文件搜索功能,并封装为类

1)首先是文件搜索类Rapidfinder的构造函数和析构函数和文件信息初始化函数和文件路径规格化函数;重新初始化文件函数

CRapidFinder::CRapidFinder(HWND MainHwnd, CString MatchName, CString MatchDir)
{
m_hThrds = NULL;
InitializeCriticalSection(&m_gCriticalSection);
ThreadSet();
FinderSet(MainHwnd, MatchName, MatchDir);
}
CRapidFinder::~CRapidFinder()
{
DeleteCriticalSection(&m_gCriticalSection);
if (m_hExitEvent)CloseHandle(m_hExitEvent);
} //初始化搜索文件信息
void CRapidFinder::FinderSet(HWND MainHwnd, CString MatchName, CString MatchDir)
{
FinderReset();
m_MainhWnd = MainHwnd; if (!MatchName.IsEmpty())
{
MatchName.MakeUpper();
MatchDir.MakeUpper();//makerupper()将CString字符转化为一个大写的字符串。
m_strFileName = MatchName;
m_Option |= OP_FILENAME;//按位或后赋值,OP_FILENAME为0x01
}
m_strFileDir = MatchDir; m_hExitEvent = CreateEvent(NULL, TRUE, FALSE, L"RAPIDFINDER");//创建事件,手动设置信号,初始化为未激发
CreatePathList();//规格化文件路径
} //初始化创建线程的信息
void CRapidFinder::ThreadSet(LONG MaxThreadCount, int priority)
{
m_Priority = priority;
m_ActiveCount = m_MaxThreadCount = MaxThreadCount;
if (m_hThrds)delete[]m_hThrds;//释放线程句柄数组
m_hThrds = new HANDLE[MaxThreadCount]; } //重新初始化文件
void CRapidFinder::FinderReset()
{
m_lpText = NULL;
m_NextVal = NULL;
m_Option = 0;
m_strFileName = "";
m_strFileDir = "";
m_DirList.RemoveAll();
ResetEvent(m_hExitEvent);//重置为未激发态
m_ExitCode = ERR;
} //规格化文件路径
void CRapidFinder::CreatePathList()
{
Trim(m_strFileDir); if (m_strFileDir.IsEmpty())
{
SetErrNo(0); return;
} int np = 0, op = 0;
CString str;
//当有多个路径同时选择时(即用;分隔)
while ((np = m_strFileDir.Find(';', op)) != -1)
{
str = Trim(m_strFileDir.Mid(op, np - op));
str.TrimRight('\\');//消除“\\”
if (!str.IsEmpty())m_DirList.AddTail((LPCTSTR)str);
op = np + 1;
}
str = Trim(m_strFileDir.Mid(op, m_strFileDir.GetLength() - op));
str.TrimRight('\\');
if (!str.IsEmpty())m_DirList.AddTail((LPCTSTR)str);
} 构造函数用来初始化临界区,初始化线程信息(线程优先级、最大线程数、线程句柄数组),初始化搜索文件信息(目录,文件名);
析构函数退出临界区,关闭事件句柄; 2)文件搜索函数的第二部分就是:判断搜索方式的MatchProc函数(是按文件名还是特定字符串);查询指定文件里是否包含特定字符的FindTextFromFile()函数;预先处理特定字符串的CalNextPos()函数 //判断搜索文件时的方式,是按文件名还是包含字符
BOOL __fastcall CRapidFinder::MatchProc(CString& findpath)
{
CString fname(findpath);
int pos = fname.ReverseFind('\\');
fname.MakeUpper();
if ((m_Option & OP_FILENAME) && (fname.Find(m_strFileName, pos + 1) == -1))return false;
if ((m_Option & OP_FILETEXT) && !FindTextFromFile(findpath))return false;
return true;
} //查询文件里是否包含我们指定的字符
BOOL __fastcall CRapidFinder::FindTextFromFile(CString& findpath)
{
CFile file;
if (NULL == file.Open(findpath.GetBuffer(0), CFile::modeRead | CFile::typeBinary))return false;
BYTE* Buffer = new BYTE[512];
int nRead;
if (!(nRead = file.Read(Buffer, 512))) { file.Close(); return false; }//如果读回字节数为0,则关闭Cfile
int i = 0, j = 0; while (j < m_TextSize)
if (j == -1 || Buffer[i] == m_lpText[j])//判断是否包含我们指定的字符
{
if (++i == nRead)//如果读回字节数为1,则只需要一轮循环集合
{
/*PeekAndPump();*/
if (!(nRead = file.Read(Buffer, 512))) { file.Close(); return false; }
i = 0;
}
j++;
}
else j = m_NextVal[j];
file.Close();
return true;
} //决定是否从下一位字符再开始匹配。比如在“aab”中搜索“ab”,当在“aab”中有重复的字符时给每一位字符设置一个是否进行到下一位匹配的标志
int* CRapidFinder::CalNextPos()
{
int j = 0, k = -1;
m_NextVal[0] = -1;
while (j < m_TextSize - 1)
if ((k == -1) || (m_lpText[j] == m_lpText[k]))
{
j++; k++;
if (m_lpText[j] != m_lpText[k])m_NextVal[j] = k;
else m_NextVal[j] = m_NextVal[k];
}
else k = m_NextVal[k];
return m_NextVal;
} 3)第三部分就是多线程的处理,包括主线程函数MainThreadProc()、子线程函数ThreadProc()、启动子线程函数StartFinder()、暂停函数PauseFinder()、停止函数StopFinder()、暂停后继续函数ResumeFinder(); //主线程函数,为每个线程分配搜索任务
DWORD WINAPI CRapidFinder::MainThreadProc(LPVOID lpParam)
{
//新建一个finder对象来存储文件信息
CRapidFinder* finder = (CRapidFinder*)lpParam; resume:
//Reset,重新开始
ResetEvent(finder->m_hExitEvent);//重置m_hExitEvent,使之处于未激发态
finder->m_ExitCode = ERR;
finder->m_ActiveCount = finder->m_MaxThreadCount; PostMessage(finder->m_MainhWnd, WM_THREADCOUNT, (WPARAM)(finder->m_ActiveCount), NULL);
//启动子线程
for (int i = 0; i < finder->m_MaxThreadCount; i++)
finder->m_hThrds[i] = StartThread(ThreadProc, lpParam); WaitForMultipleObjects(finder->m_MaxThreadCount, finder->m_hThrds, TRUE, INFINITE);//等待所有线程返回 for (int i = 0; i < finder->m_MaxThreadCount; i++)
CloseHandle(finder->m_hThrds[i]); //关闭所有线程句柄 //查看线程退出原因
switch (finder->m_ExitCode)
{
case PAUSE:SendMessage(finder->m_MainhWnd, WM_THREADPAUSE, NULL, NULL);
ResetEvent(finder->m_hExitEvent);//重置为未激发态,为暂停后重新开始做准备
//等待继续查找
WaitForSingleObject(finder->m_hExitEvent, INFINITE);
goto resume;
//下面两个类似,一个是直接退出,一个是执行完退出
case EXIT:SendMessage(finder->m_MainhWnd, WM_THREADEXIT, EXIT, NULL);
finder->FinderReset();
break;;
case STOP:SendMessage(finder->m_MainhWnd, WM_THREADEXIT, STOP, NULL);
finder->FinderReset();
break;
default:finder->SetErrNo(1); return 0;
}
return 1;
} //启动子线程的函数
HANDLE CRapidFinder::StartThread(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParam)
{
DWORD ThreadID;//线程id
CRapidFinder* finder = (CRapidFinder*)lpParam;//文件搜索类对象 HANDLE htmp = CreateThread(NULL, 0, lpStartAddress, lpParam, CREATE_SUSPENDED, &ThreadID);
BOOL re = SetThreadPriority(htmp, finder->m_Priority);
ASSERT(re);
ResumeThread(htmp);
return htmp;
} 上述两个函数相互配合,创建指定数目的子线程(在StartFinder()函数初始化子线程信息,创建子线程);主线程使用WaitForMultipleObjects函数等待所有子线程返回,在全部返回后关闭所有句柄;
并且主线程还监听和处理子线程的状态,根据m_ExitCode判断子线程是处于暂停、停止还是暂停后继续的状态(即文件搜索中的暂停、停止、暂停后继续的功能),然后通过设置m_hExitEvent事件对象的激发状态来控制子线程的工作; 2、文件搜索中的开始、暂停、暂停后继续、停止函数
//开始查找
BOOL CRapidFinder::StartFinder()
{ if (m_DirList.IsEmpty()) { SetErrNo(0); return FALSE; }
PostMessage(m_MainhWnd, WM_THREADCOUNT, (WPARAM)m_ActiveCount, NULL); DWORD ThreadID;
//创建主线程
HANDLE hMainThread = CreateThread(NULL, 0, MainThreadProc, (LPVOID)this, CREATE_SUSPENDED, &ThreadID); //线程是在挂起状态下创建的,并且在调用ResumeThread函数之前不会运行 。
ASSERT(hMainThread);
BOOL re = SetThreadPriority(hMainThread, m_Priority);//调整优先级
ASSERT(re);//作用是如果它的条件返回错误,则终止程序执行
ResumeThread(hMainThread);
CloseHandle(hMainThread); return TRUE;
}
//暂停查找
void CRapidFinder::PauseFinder()
{
if (m_ExitCode == PAUSE)return;
m_ExitCode = PAUSE;
SetEvent(m_hExitEvent);//发出m_hExitEvent信号
Sleep(40);
}
//继续查找
void CRapidFinder::ResumeFinder()
{
SetEvent(m_hExitEvent);
}
//停止查找
void CRapidFinder::StopFinder()
{
if (m_ExitCode == STOP)return; if (m_ExitCode == PAUSE)
{
ResumeFinder();//重新开始
Sleep(40);//延时
}
m_ExitCode = STOP;
SetEvent(m_hExitEvent);
}
在StartFinder()中创建主线程;暂停、暂停后继续、停止都是通过改变m_hExitEvent的激发状态来实现
因为创建m_hExitEvent事件时:CreateEvent(NULL, TRUE, FALSE, L"RAPIDFINDER");是手动重置激发状态,所以在主函数的个状态的处理逻辑里每次都需要先用resetEvent()重置激发态

2、MFC界面

主要用到了mfc的按钮控件、Edit控件和list控件

主要界面布局如上

相关成员的定义:

事件处理程序(函数)的实现

1)MFC类的初始化,对相关成员变量赋初值;以及对话框界面的初始化(设置菜单,图标),另外还使用到了CListCtrl控件来显示搜索到的文件信息

CFinderDemoDlg::CFinderDemoDlg(CWnd* pParent /=NULL/)
: CDialog(CFinderDemoDlg::IDD, pParent)
{ //{{AFX_DATA_INIT(CFinderDemoDlg)
m_ActiveCount = _T("0");
m_folder = _T("");//C:\;D:\;E:\;F:");
m_count = _T("0");
m_findfolder = _T("");
m_text = _T("");
m_filename = _T("");
m_threadcount = 10;
m_priority = 0;
//}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_folder=GetAllDriverList();
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);//图标 } //初始化对话框
BOOL CFinderDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); m_ListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_TRACKSELECT|LVS_EX_FLATSB|LVS_EX_UNDERLINEHOT|LVS_EX_GRIDLINES);//具体参考https://docs.microsoft.com/zh-cn/windows/win32/Controls/extended-list-view-styles m_ListCtrl.InsertColumn(0,T("文件名"),LVCFMT_IMAGE|LVCFMT_LEFT,80,80);//插入一列
m_ListCtrl.InsertColumn(1,T("路径"),LVCFMT_LEFT,180);
m_ListCtrl.InsertColumn(2,T("大小"),LVCFMT_LEFT,80);
m_ListCtrl.InsertColumn(3,T("类型"),LVCFMT_LEFT,80);
m_ListCtrl.SetHoverTime(500);//设置列表视图控件的当前逗留时间 finder.ThreadSet(30);
m_ListCtrl.SetRedraw();//数据更新时闪烁
UIControl(false); CMenu* pSysMenu = GetSystemMenu(FALSE);// 返回当前使用窗口菜单的拷贝的句柄。该拷贝初始时与窗口菜单相同,但可以被修改。 if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);//画一条水平区分线
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);//将IDM_ABOUTBOX添加到菜单中
}
} //设置图标
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control
}

2)数据交换函数和消息响应函数

将控件的值传给类中的将变量的值显示到控件上;以及对相关消息的响应函数(如开始、暂停、显示“正在查找的文件”的函数…)

void CFinderDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFinderDemoDlg)
//将控件的值传递给指定变量假设为类型1,将变量的值传递给控件假设为类型2
DDX_Control(pDX, IDC_LIST, m_ListCtrl);//类型2
DDX_Control(pDX, IDC_STOP, m_stop);//将IDC_STOP窗口的值传递给m_stop
DDX_Control(pDX, IDC_PAUSE, m_pause);//类型1
DDX_Control(pDX, IDC_START, m_start);//类型1
DDX_Text(pDX, IDC_ACTIVE_THREAD, m_ActiveCount);//将m_ActiveCount的值显示到IDC_ACTIVE_THREAD窗口
DDX_Text(pDX, IDC_FOLDER, m_folder);//类型1
DDX_Text(pDX, IDC_COUNT, m_count);//类型2
DDX_Text(pDX, IDC_FINDING_FOLDER, m_findfolder);//将m_findfolder的值显示到IDC_FINDING_FOLDER窗口
DDX_Text(pDX, IDC_INCLUDE_TEXT, m_text);//类型1
DDX_Text(pDX, IDC_FILENAME, m_filename);//类型1
DDX_Text(pDX, IDC_THREAD_NO, m_threadcount);//类型1
//DDX_Text(pDX, IDC_PRIORITY, m_priority);
//}}AFX_DATA_MAP
} BEGIN_MESSAGE_MAP(CFinderDemoDlg, CDialog)//添加消息响应函数,为每个消息处理函数加入一个入口。
ON_WM_SYSCOMMAND()//系统消息
ON_WM_PAINT()//绘图消息
ON_WM_QUERYDRAGICON()//查询icon消息
ON_BN_CLICKED(IDC_STOP, OnStop)//停止
ON_BN_CLICKED(IDC_START, OnStart)//开始
ON_BN_CLICKED(IDC_PAUSE, OnPause)//暂停
ON_BN_CLICKED(IDC_BROWSE, OnBrowse)//选择文件
ON_EN_CHANGE(IDC_THREAD_NO, OnChangeThreadNo)//设置线程数
ON_MESSAGE(WM_THREADEXIT, OnFindExit)//查找时停止
ON_MESSAGE(WM_THREADCOUNT, OnFindThreadCount)
ON_MESSAGE(WM_FINDERITEM , OnFindItem)
ON_MESSAGE(WM_THREADPAUSE, OnFindPause)//查找时暂停
ON_MESSAGE(WM_FINDERFOLDER, OnFindingFolder)//正在查找
ON_EN_CHANGE(IDC_FOLDER, &CFinderDemoDlg::OnEnChangeFolder)
END_MESSAGE_MAP()

3)文件相关函数,OnBrowse()选择在哪个路径进行查找文件;修改查找文件的线程数的OnChangeThreadNo()函数;

点击选择文件按钮,触发OnBrowse事件处理函数,打开选择文件路径的面板;在mfc界面上设置线程数目,通过值交换函数,将控件上的值赋给相关类的成员变量,再通过OnChangeThreadNo()函数修改创建线程是默认设置的线程数目为新的值

//选择查找文件路径

void CFinderDemoDlg::OnBrowse()
{
// TODO: Add your control notification handler code here
BROWSEINFO bi;
char dispname[MAX_PATH], path[MAX_PATH];
ITEMIDLIST* pidl;
//
bi.hwndOwner = m_hWnd;
bi.pidlRoot = 0;
bi.pszDisplayName = dispname;
bi.lpszTitle = "请选择查找目录:";
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_DONTGOBELOWDOMAIN;
bi.lpfn = 0;
bi.lParam = 0;
bi.iImage = 0;
if (pidl = SHBrowseForFolder(&bi))
{
SHGetPathFromIDList(pidl, path);
m_folder = CString(path);
if (m_folder.IsEmpty())m_folder = GetAllDriverList();
UpdateData(false);
}
} //当用户未指定查找路径时的默认路径
CString CFinderDemoDlg::GetAllDriverList()
{
CString tmp = _T("D:"), Dir;//D:
for (int i = 1; i <= 25; i++)
{
Dir = CString("D:" + i) + _T(":");
if (GetDriveType(Dir.GetBuffer(0)) == DRIVE_NO_ROOT_DIR)continue;//判断该路径是否是有效的
tmp += ";" + Dir;
}
return tmp;
} //修改默认的线程数为我们MFC界面选择的线程数 void CFinderDemoDlg::OnChangeThreadNo()
{
int count=GetDlgItemInt(IDC_THREAD_NO);
if(count<1||count>99){count=10;SetDlgItemInt(IDC_THREAD_NO,count);}
//finder.ThreadSet(count,finder.GetThreadPrioriy());
finder.ThreadSet(count, m_priority);
}

4)开始、暂停、停止查找文件的函数

//开始
void CFinderDemoDlg::OnStart() {
// TODO: Add your control notification handler code here
// ::SendMessage(GetSafeHwnd(),WM_THREADCOUNT,(WPARAM)100,NULL);
UpdateData(true);//刷新控件的值到变量
m_count = _T("0");
m_ActiveCount = _T("0");
count = 0;
m_imglist.DeleteImageList();
m_imglist.Create(16, 16, ILC_MASK | ILC_COLORDDB, 1, 100);//新建一个图像列表,然后用add添加图标(这里在OnFindItem函数使用到了)
m_ListCtrl.SetImageList(&m_imglist, LVSIL_SMALL);//再将该列表中的图像绑定到m_ListCtrl列表控件上
m_ListCtrl.DeleteAllItems();
UpdateData(false);//将变量刷新到控件进行显示
finder.FinderSet(GetSafeHwnd(), m_filename, m_folder);
finder.FindWithText(m_text, m_text.GetLength());
finder.StartFinder();
UIControl(true);//开始后就调用UIControl进制相关控件接收鼠标或键盘消息
} //暂停
void CFinderDemoDlg::OnPause()
{
// TODO: Add your control notification handler code here
static BOOL ispause = true;
if (ispause)
{
m_pause.SetWindowText("继续");//如果是暂停状态就将按钮修改为“继续”
finder.PauseFinder();
ispause = false;
}
else
{
m_pause.SetWindowText("暂停");
finder.ResumeFinder();
ispause = true;
}
} //停止
void CFinderDemoDlg::OnStop()
{
// TODO: Add your control notification handler code here
finder.StopFinder();
} //弹出框
LRESULT CFinderDemoDlg::OnFindExit(WPARAM wparam, LPARAM lparam) {
m_pause.SetWindowText("暂停");
UIControl(false);
if (wparam == 1)AfxMessageBox("停止查找!");//:AfxMessageBox比MessageBox简单一些,因为它是一个全局函数所以不需要对应的一个窗口类,但是不能控制消息框标题
else AfxMessageBox("查找结束!");
m_ListCtrl.RedrawItems(0, count - 1);//暂停时只显示现在查到的
return 0;
}
LRESULT CFinderDemoDlg::OnFindPause(WPARAM wparam, LPARAM lparam)
{
AfxMessageBox("用户暂停!");
return 0;
}

5)界面更新函数,如更新当前活动线程数,查找到符合的文件数目,开始、暂停、停止的按钮状态,显示正在查找的文件,显示已经找到的符合的文件

LRESULT CFinderDemoDlg::OnFindExit(WPARAM wparam,LPARAM lparam)
{
m_pause.SetWindowText("暂停");
UIControl(false);
if(wparam==1)AfxMessageBox("停止查找!");//:AfxMessageBox比MessageBox简单一些,因为它是一个全局函数所以不需要对应的一个窗口类,但是不能控制消息框标题
else AfxMessageBox("查找结束!");
m_ListCtrl.RedrawItems(0,count-1);//暂停时只显示现在查到的
return 0; } LRESULT CFinderDemoDlg::OnFindPause(WPARAM wparam,LPARAM lparam)
{
AfxMessageBox("用户暂停!");
return 0;
} //查找到的文件的文件信息
LRESULT CFinderDemoDlg::OnFindItem(WPARAM wparam,LPARAM lparam) {
m_count.Format("%d",++count);
UpdateData(false);
CString pathname=*((CString *)wparam);
CFileStatus Status;
CFile::GetStatus(pathname,Status);
CString Unit="Byte";
float flen=(float)Status.m_size;
if(flen>1024)
{
flen/=1024;
if(flen<1024){Unit="KB";}
else{flen/=1024;Unit="MB";}
} CString Size;
Size.Format("%1.2f",flen);
int pos=pathname.ReverseFind('');
SHFILEINFO sfi;
if (::SHGetFileInfo (pathname, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO),SHGFI_USEFILEATTRIBUTES | SHGFI_DISPLAYNAME | SHGFI_TYPENAME |SHGFI_ICON|SHGFI_SMALLICON ))
{
//更新mfc界面的list框显示
m_imglist.Add(sfi.hIcon);
m_ListCtrl.InsertItem(count-1,sfi.szDisplayName,count-1);
m_ListCtrl.SetItemText(count-1,1,pathname.Mid(0,pos));
m_ListCtrl.SetItemText(count-1,2,(Size+Unit));
m_ListCtrl.SetItemText(count-1,3,sfi.szTypeName);
}
m_ListCtrl.Update(count-1);
PeekAndPump();
return 0; } //在MFC界面显示当前活动的线程数
LRESULT CFinderDemoDlg::OnFindThreadCount(WPARAM wparam,LPARAM lparam)
{
m_ActiveCount.Format("%ld",LONG(wparam));
UpdateData(FALSE);
return 0;
} //在mfc界面显示当前正在查询的文件路径
LRESULT CFinderDemoDlg::OnFindingFolder(WPARAM wparam,LPARAM lparam)
{
m_findfolder=*((CString *)wparam);
UpdateData(false);
return 0;
} /控制相关控件的状态
void CFinderDemoDlg::UIControl(BOOL bOp)//start with true;
{
m_start.EnableWindow(!bOp);
m_stop.EnableWindow(bOp);
m_pause.EnableWindow(bOp);
GetDlgItem(IDC_THREAD_NO)->EnableWindow(!bOp);//EnableWindow函数允许/禁止指定的窗口或控件接受鼠标和键盘的输入
GetDlgItem(IDC_SPIN_THREAD_NO)->EnableWindow(!bOp);
}

windows核心编程课程实践---多线程文件搜索器(MFC界面)的更多相关文章

  1. 【Windows核心编程】一个使用内存映射文件进行进程间通信的例子

    进程间通信的方式有很多种,其底层原理使用的都是内存映射文件. 本文实现了Windows核心编程第五版475页上的demo,即使用内存映射文件来在进程间通信. 进程1 按钮[Create  mappin ...

  2. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  3. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  4. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  5. windows核心编程---第八章 使用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...

  6. 《Windows核心编程》第一讲 对程序错误的处理

    一个Windows函数通常都有一个有意义的返回值类型,它标志着这个函数的运行状态,即函数运行成功与否.windows常用的函数类型如下图: 从系统内部来讲,当一个Windows函数检测到一个错误时,它 ...

  7. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  8. 【Windows】windows核心编程整理(上)

    小续 这是我11年看<windows核心编程>时所作的一些笔记,现整理出来共享给大家 windows核心编程整理(上) windows核心编程整理(下) 线程的基础知识 进程是不活泼的,进 ...

  9. 《windows核心编程系列》十七谈谈dll

    DLL全称dynamic linking library.即动态链接库.广泛应用与windows及其他系统中.因此对dll的深刻了解,对计算机软件开发专业人员来说非常重要. windows中所有API ...

随机推荐

  1. Day_10【常用API】扩展案例1_利用人出生日期到当前日期所经过的毫秒值计算出这个人活了多少天

    分析以下需求,并用代码实现: 1.从键盘录入一个日期字符串,格式为 xxxx-xx-xx,代表该人的出生日期 2.利用人出生日期到当前日期所经过的毫秒值计算出这个人活了多少天 package com. ...

  2. 基于C语言的Q格式使用详解

    用过DSP的应该都知道Q格式吧: 目录 1 前言 2 Q数据的表示 2.1 范围和精度 2.2 推导 3 Q数据的运算 3.1 0x7FFF 3.2 0x8000 3.3 加法 3.4 减法 3.5 ...

  3. Ubuntu 配置/etc/fstab参数实现开机自动挂载硬盘

    文章目录 前言 fstab 参数含义 实现步骤 1 查看硬盘信息,并找到需要进行挂载的硬盘 2 sudo mkfs.ext4 /dev/sdc 3 sudo mkdir /home/diska 4 查 ...

  4. Autohotkey心得

    玩游戏,烧钱和作弊是永恒的话题,热键一定程度上和作弊相关.办公用数据库.编程.商业智能,一定程度上也是作弊,欺负没有相关信息技术的公司.个人. 避免和输入法产生冲突,少用Send,多用剪切板中转. E ...

  5. jvm入门及理解(五)——运行时数据区(虚拟机栈)和本地方法接口

    一.虚拟机栈背景 由于跨平台性的设计,java的指令都是根据栈来设计的.不同平台CPU架构不同,所以不能设计为基于寄存器的. 优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要 ...

  6. 为什么PUSH推送要经常背锅?

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 自从做了推送以后,每隔一段时间就发现有各大的公司 ...

  7. [ACdream 1212 New Year Bonus Grant]贪心

    题意:员工之间形成一棵树,上级可以给下级发奖金,任何一个人最多可以给一个下级发,并且发了奖金后就不能接受奖金.求总共最多可以产生多少的奖金流动 思路:每次选择没有下级并且有上级的员工a,令它的上级为b ...

  8. Centos ps命令

    输出格式(ps -aux) USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND VSZ:占用的虚拟内存大小() RSS: COMMAND: 执 ...

  9. js 获取URL后面传的参数

    function GetRequest() { var url = location.search; //获取url中"?"符后的字串 var theRequest = new O ...

  10. day08文件的操作(0221)

    #1.文件操作之追加数据01:f = open("yesterday01",'a+U',encoding="utf-8")#a= append,追加之意,w则为 ...