Window核心编程
第一章:错误处理
FormatMessage/LocalLock\LocalFree

第二章:
TEXT("..") TCHAR(CHAR,WCHAR) 
安全字符串函数 (必须在包含其他所有文件之后才包含StrSafe.h)
_tcscpy  _tcscpy_s
_CrtSetReportMode(_CRT_ASSERT,0); //禁止可能由C运行时触发的所有Debug Assertion Failed对话框。
TCHAR szBuffer[10] = {....}
_tcscpy_s(szBuffer,_countof(szBuffer),TEXT("0123456789")); //最终的字符串被截断为一个空字符串。
StringCchCat(EX)\StringCchCopy(EX)\StringCbCat(EX)\StringCbCopy(EX)
Cch Count of Characters    Cb 字节
最理想比较函数 CompareString(Ex) \CompareStringOrdinal
CompareStringW(
    __in LCID     Locale,
    __in DWORD    dwCmpFlags,
    __in_ecount(cchCount1) PCNZWCH lpString1,
    __in int      cchCount1,
    __in_ecount(cchCount2) PCNZWCH  lpString2,
    __in int      cchCount2);
LCID GetThreadLocale(void)
为了比较程序内部所用的字符串,应该使用CompareStringOrdinal(只支持unicode)
CompareStringOrdinal(
    __in LPCWSTR lpString1,
    __in int     cchCount1,
    __in LPCWSTR lpString2,
    __in int     cchCount2,
    __in BOOL    bIgnoreCase
);//码位比较,不考虑区域设置,速度相对快。
TCHAR/PTSTR/BYTE/PBYTE/TEXT/_T/_countof而不用sizeof, malloc(nCharacters * sizeof(TCHAR))
MultiByteToWideChar / WideCharToMultiByte
IsTextUnicode //可能有错

第三章:内核对象
由于内核对象的数据结构只能由OS内核访问,所以应用程序不能在内存中定位这些数据结构并直接更改内容。
内核对象是和进程相关的,另一进程调用该进程下的内核对象就可能失败
使用计数是所有内核对象类型都有的一个数据成员。
几乎所有创建内核对象的函数都有一个PSECURITY_ATTRIBUTES参数,相反创建用户对象或GDI对象的函数都没有PSECURITY_ATTRIBUTES参数
由于句柄值实际是作为进程句柄表的索引来使用的,所以句柄是与当前这个进程相关的。
内核对象都要调用CloseHandle向系统表明结束使用内核对象,还应同时设这个变量为NULL
跨进程边界共享内核对象:
a.利用文件映射对象 //同台机器不同进程共享数据块
b.借助邮件槽和命名管道 //网络上不同机器不同进程相互发送数据块
c.互斥量,信号量和事件 //允许不同进程中的线程同步执行  通知
三种机制来允许进程共享内核对象:
a.使用对象句柄继承,b.为对象命名,c.复制对象句柄。
a.使用对象句柄继承:对象够本的继承只会在生成子进程的时候发生,假如父进程后来又创建了新的内核对象,并同时将它们的句柄设为可继承的句柄。
 那么正在运行的子进程是不会继承这些新句柄的。
 改变句柄标志 SetHandleInformation
b.为对象命名:并不是所有内核对象都可以进行命名 //防止重名,可用GUID或命名空间
 CreateMutex\CreateEvent\CreateSemaphore\....创建有名的内核对象
 进程A: HANDLE hMutexProcessA = CreateMutex(NULL,FALSE,TEXT("JeffMutex");
 1-->进程B: HANDLE hMutexProcessB = CreateMutex(NULL,FALSE,TEXT("JeffMutex"); if(GetLastError() == ERROR_ALREADY_EXISTS)
 2-->进程B: HANDLE hMutexProcessB = OpenMutex(.....); if(GetLastError() == ERROR_ALREADY_EXISTS)
 终端服务命名空间
 一个服务的命名内核对象始终位于全局命名空间内的。默认情况下,在终端服务中,在终端服务中,应用程序自己的命名内核对象在会话的命名空间内。
 HANDLE h = CreateEvent(NULL,FALSE,FALSE,TEXT("Global\\MyName"));
 HANDLE h = CreateEvent(NULL,FALSE,FALSE,TEXT("Local\\MyName"));
 专有命名空间 ????????

第四章:进程
  GUI  Int WINAPI _tWinMain(HINSTANCE ....)
  CUI  int _tmain(int argc,TCHAR *argv[],TCHAR *envp[])
OS的加载程序(loader)会检查可执行文件的文件头,并获取链接时链接器开关/SUBSYSTEM:CONSOLE \ /SUBSYSTEM:WINDOWS的值,如是CUI,加载程序会自动确保有一个可用的文本控制
 台窗口(如命令提示符启动),如有必要也会创建一个窗口。如果是GUI,则只负责加载。
 WinMainCRTStartup\wWinMainCRTStartup --> _tWinMain
 mainCRTStartup\wmainCRTStartup  --> _tmain
 
c/c++运行库启动函数
1)---> 1.获得命令行指针;2.获得环境指针;3.初始化c\c++运行库全局变量;4.初始化C运行库malloc\calloc\IO例程使用的堆;5.调用所有全局和静态C++类对象的构造函数。
2)---> 1.GetStartupInfo(&StartupInfo);
    2.int nMainRetVal = _tWinMain((HINSTANCE)&__ImageBase,NULL,pszCommandLineAnsi,(StartupInfo.dwFlags & STARTF_USESHOWWINDOW)?,StartupInfo.wShowWindow:SW_SHOWDEFAULT);
3)--->入口点函数返回后,启动函数将调用C运行库函数exit,向其传递返回值(nMainRetVal).
    exit执行:1.调用_onexit函数;2.调用全局、静态C++类对象的析构函数;3.如DEBUG中需要则生成内在泄漏报告;4.调用OS的ExitProcess(nMainRetVal).

进程实例句柄
 WinMain中的hInstance实际值是一个内存基地址;系统将可执行文件 的映像加载到进程地址空间中的这个位置,这个由链接器决定。
 如果想知道一个可执行文件或DLL文件被加载进程地址空间什么位置,可用:HMODULE GetModuleHandle(PCTSTR pszModule); pszModule 为NULL时返回主调进程的可执行文件基地址。
 在一个DLL中可用伪变量__ImageBase(extern "C" const IMAGE_DOS_HEADER _ImageBase;) 或 GetModuleHandleEx可返回DLL的基地址
 调用GetModuleHandle(NULL)的代码是在一个DLL文件中,返回值仍是可执行文件的基地址,而非DLL文件的基地址。
 第二个hPrevInstance方便移植16bit window
 #define UNREFERENCED_PARAMETER(P)          (P)   消息声明未引用告警
 GetCommandLine() GetEnvironmentStrings
 WM_SETTINGCHANGE //促使应用程序立即更新它们的环境块
 
 VerifyVersionInfo 判断主机系统是否符合应用程序要求
 进程内核对象不是进程本身,而是OS用来管理这个进程的一个小型数据结构。系统为新进程的主线程创建一个线程内核对象。
 默认情况下,所有16位windows应用程序都在一个共享的VDM(virtual DOS machine)中执行。
 IsWow64Process(__in   HANDLE hProcess,  __out  PBOOL Wow64Process)
 
 GetCurrentProcessId\GetCurrentThreadId\GetProcessId\GetThreadId\GetProcessIdOfThread(指定线程所在进程)
 如果在入口点函数中调用的是ExitThread,而不是ExitProcess或者入口点函数直接返回,应用程序的主线程将停止执行,但只要进程中还有其他线程正在运行,进程就不会终止。
 
 //断绝父子进程关系
 BOOL fSuccess = CreatePorcess(...,&pi);
 if(fSuccess){
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
 }
 手动提升进程的权限ShellExecuteEx
 IsUserAnAdmin\\Tests whether the current user is a member of the Administrator's group.

第五章 作业
 作业对象可以想象成一个进程窗口,“沙箱“
 BOOL WINAPI IsProcessInJob(
  __in      HANDLE ProcessHandle,
  __in_opt  HANDLE JobHandle,
  __out     PBOOL Result ); //如果进程已与一个作业关联,就无法将当前进程或者它的任何子进程从作业中去除,这个安全特性确保进程无法摆脱作业对它的限制
 
  默认情况下,Windows资源管理器启动一个应用程序都会放到名为PCA...专用作业中,(program Compatibility Assistant) 这纯粹解决兼容问题
  调试器如关联了这个作业,调试对象自动关联这个作业,可以命令行启动调试器,这个就不会关联这个作业
  CreateJobObject\SetInformationJobObject\AssignProcessToJobObject\CloseHandle
  UserHandleGrantAccess 授权作业内进程对作业外用户对象的访问
  TerminateJobObject ”杀死“作业内部的所有进程,类似每个进程调用TerminateProcess

第六章 线程基础
 进程:一个进程内核对象+一个地址空间
 线程:一个线程内核对象+一个线程栈
 每个线程都有其CPU寄存器,称为线程的上下文(context)
 CONTEXT结构本身保存在纯种内核对象中。
 创建初始化线程 IP->RtlUserThreadStart
 VOID RtlUserThreadStart(PTHREAD_START_ROUTINE pfnStartAddr,PVOID PVParam){
  __try{
   ExitThread((pfnStartAddr(pvParam));
  }
  __except(UnhandleExceptionFilter(GetExceptionInformation())){
   ExitProcess(GetExceptionCode());
  }
  //NOTE: we never get here
 }
 
 当模块链接到CRT的DLL时,这个库会在线程终止时收到DLL_THREAD_DETACH通知,并会释放_tiddata块,但仍然强烈建议用_beginthreadex
 
 HANDLE GetCurrentProcess()
 HANDLE GetCurrentThread()
 这两函数返回的是伪句柄,不会在相应的句柄表中新建句柄,不会影响使用计数,如果调用CloseHande,并传入伪句柄,CloseHandle只是简单地忽略些调用。
 
 线程的伪句柄是一个指向当前线程的句柄
 DuplicateHandle 可以转换伪句柄成真正的句柄,现此函数之后要调用CloseHandle递减下使用计数。
 
第七章:线程调度、优先级和关联性
 ResumeThread\SuspendThread
 SuspendThread调用须小心,如果此线程正在分配堆中内存,线程将锁定堆,其他线程将不能访问堆。
 WaitForDebugEvent //挂起进程内所有线程 ContinueDebugEvent
 也可通过CreateToolhelp32Snapshot函数去遍历所有线程并挂起。
 Sleep(0) //主调线程放弃了时间片的剩余部分,它强制系统调度其他线程。但可能调度自己。
 SwitchToThread 与 Sleep(0) 不同的是它允许执行低优先级线程。
 GetThreadTime\GetProcessTime
 SuspendThread->GetThreadContext //查看线程的内核对象的内部,一个线程实际上有两个上下文:用户模式,内核模式
 SetThreadcontext 改变EIP值可以终止相应进程。
 线程优先级0-31    0优先级的页面清零线程。线程优先级是相对进程优先级的
 SetProcessPriorityBoost\SetThreadPriorityBoost 允许/禁止动态提升优先级
 
第八章:用户模式下的线程同步
 原子访问、调整缓存行、高级线程同步、关键段、Slim读/写锁、条件变量

点【关闭】
DefWindowProc 检测鼠标向窗口发送WM_SYSCOMMAND
DefWindowProc响应WM_SYSCOMMAND便发送WM_CLOSE
DefWindowProc调用destroywindow响应WM_CLOSE
destroywindow便发送WM_DESTYOY
DefWindowProc调用Postquitmessage响应WM_DESTYOY
Postquitmessage便发送WM_QUIT

WM_PAINT消息触发事件:
1.用户移动一个窗口,导致原来被遮盖的部分窗口暴露出来;
2.用户调整窗口的大小;(CS_HREDRAW  | CS_VERDRAW )
3.ScrollWindow || ScrollDC || InvalidateRect || InvalidateRgn

BeginPaint & EndPaint 成对使用
GetDC & ReleaseDC 成对使用,但相比上面的,不会使区域有效,需要手动调用validateRect(hwnd,NULL)
GetWindowDC 用于整个窗口,比GetDC 多包含非客户区
CreateDC & DeleteDC    CreateDC(TEXT"DISPLAY"),NULL,NULL,NULL) 返回当前整个屏幕的设备环境句柄 GetDC使用NULL参数也可获得当前整个屏幕的设备环境句柄

TEXTMETRICS tm;
hdc = GetDC(hwnd);
GetTextMetrics(hdc,&tm);
ReleaseDC(hdc);

立刻更新无效区域:可以在调用InvalidateRect后调用UpdateWindow.

图形输出设备分为两大类:光栅设备(raster device) 和 矢量设备(vector device)
光栅:以点来绘图   矢量:以线条绘图

CreateIC 函数获取一个“信息上下文”  CreateCompatibleDC \ CreateMetaFile & CloseMetaFile 图元文件

注册窗口类时style有CS_OWNDC时,相应窗口会有私有的DC,则只需要初始化一次,否则每次使用得初始化;
这个CS_OWNDC只影响GetDC & BeginPaint , 其他函数不受影响。
idSaved = SaveDC(hdc);
RestoreDC(hdc,idSaved);
RestoreDC(hdc,-1); //恢复到最近一次由SaveDC函数保存的状态。

SetPixel(hdc,x,y,crColor); //设备坐标像素点特定颜色  多次调用性能低。
crColor = GetPixel(hdc,x,y);

一个程序可以创建6种GDI对象:画笔,画刷,位图,区域,字体和调色板,除调色板外,其余用SelectObject函数选入设备环境。

填充空隙的颜色是由设备环境的两个属性(背景模式和背影颜色)决定
SetBkColor(hdc,crColor);
SetBkMode(hdc,TRANSPARENT);

如果使用带“DISPLAY"参数的CreateDC函数获得整个屏幕的设备环境,那逻辑坐标值将默认映射屏幕坐标
客户区坐标,屏幕坐标 ClientToScreen & ScreenToClient

映射模式被定义为从”窗口“(window)(逻辑坐标)到”视口“(viewport)(设备坐标)的映射
窗口:描述一个程序战胜屏幕的区域
视口:含有”剪切区域“之意。

FillRect & FrameRet & InvertRect(翻转所有像素1->0,0->1)
OffsetRect\InflateRect\SetRectEmpty\CopyRect\IntersectRect\UnionRect\IsRectEmpty\PtInRect

PeekMessage 空闲时处理,一旦有消息加载到程序的消息队列中就释放控制。
GetMessage函数并不把控制权交还给程序,除非获得消息。

while(GetMessage(&msg,NULL,0,0))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
 return msg.wParam;
替换后:\\overlay optimize
 while(TRUE)
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   if(msg.messgae == WM_QUIT)
    break;
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  else
  {
   do some other work;
  }
 }
 return msg.wParam;

CreateRectRgn\CreateRectRgnIndirect\CreateEllipticRgn\createEllipticRgnIndirect\CreatePolygonRgn\CombinRgn
InvalidteRect\ValidateRgn

具有输入焦点的窗口要么是活动,要么是活动窗口的子孙窗口。
活动窗口总是最上层的窗口。
窗口过程通过捕获WM_SETFOCUS\WM_KILLFOCUS消息来确定自己的窗口是否具有输入焦点。\\overlay optimize

键盘和鼠标消息最初放入到单独的消息队列(系统消息队列),仅当windows应用程序完成了对前一个用户输入消息的处理后,
Window才从系统消息队列中取出下一条消息,并把它放入应用程序消息队列中。

键盘事件的消息可分为击键和字符。

系统键击和非系统键击,SYS类表明该击键对Windows比对Windows应用程序更加重要。当输入键和Alt键组合时通常产生的是系统键击
WM_KEYDOWN\WM_KEYUP\WM_SYSKEYDOWN\WM_SYSKEYUP    \\optimize overlay window is foreground window.  GetFocus

TranslateMessage函数负责把击键消息转换为字符消息。

字符消息分四类
         字符       死字符
 非系统字符   WM_CHAR      WM_DEADCHAR    //这两来自WM_KEYDOWN
 系统字符    WM_SYSCHAR    WM_SYSDEADCHAR  //这两来自WM_SYSKEYDOWN

WM_CHAR wParam参数是ANSI或Unicode字符码 
 IsWindowUnicode(hwnd)
如果需要读取输入到窗口中的键盘字符,就处理WM_CHAR消息;如果需要读取光标,功能键,Delete键,Insert键,Shift,Ctrl,Alt键,则处理WM_KEYDOWN消息。
 WM_INPUTLANGCHANGE 切换输入时系统派发此消息到窗口过程

GetFocus() This function retrieves the handle to the keyboard focus window associated with the thread that called the function.
WM_SETFOCUS\WM_KILLFOCUS

CreateCaret\SetCaretPos\ShowCaret\HideCaret\DestroyCaret
 
第七章:鼠标
GetSystemMetrics(SM_MOUSEPRESENT) \\判断是否连接鼠标
GetSystemMetrics(SM_CMOUSEBUTTONS) \\获得鼠标按钮个数
窗口类style = CS_DBLCLKS,则窗口过程能接收鼠标双击消息。

WM_NCHITTEST "非客户区击中测试”
case WM_NCHITTEST:
 return (LRESULT) HTNOWHERE;  //可以阻止系统向窗口发送所有客户区和非客户区鼠标消息。
Windows会利用WM_NCHITTEST消息来产生所有其他和氥位置相关的鼠标消息。

ShowCursor \ GetCursorPos \ SetCursorPos
idChild = GetWindowLong(hwnd,GWL_ID) \ GetKlgCtrlID(hwnd)
hwndChild = GetDlgItem(hwndParent,idChild);
SetCapture \ ReleaseCapture \ SetROP2
鼠标滚轮的滚动使Windows产生WM_MOUSEWHEEL消息,并发送给具有输入焦点的窗口。

第八章:计时器
WM_TIMER\WM_PAINT都是低优先级的,只有当消息队列中没有其他消息时,程序才会收到它们。
Windows把在消息队列时的多个WM_TIMER\WM_PAINT消息结合成一条消息。
WM_TIMER中wParam为计时器ID
MessageBeep函数产生一个响铃声
GetLocalTime

第九章:子窗口控件
子窗口控件向父窗口WM_COMMAND消息
LOWORD(wParam) 子窗口ID
HIWORD(wParam) 通知码
LParam     子窗口句柄
按钮通知码有:BN_CLICKED\BN_PAINT\BN_SETFOCUS\BN_KILLFOCUS\.....
通知码需要在按钮style里相应设置才会发送,如设置BS_NOTIFY,通知码BN_SETFOCUS\BN_KILLFOCUS才会发送。
8个按钮消息,以BM_开头
SetWindowText \ GetWindowText
ShowWindow \IsWindowVisible \ EnableWindow \ IsWindowEnable
WM_SYSCOLRCHANGE
BS_OWNERDRAW STYLE允许自绘按钮  在需要重绘按钮时,它会向其父窗口发送WM_DRAWITEM消息。DrawFocusRect画选中按钮时的虚框。

滚动条类 窗口滚动条和滚动条控件 //滚动条控件不同按钮控件发送WM_COMMAND,而是和窗口滚动条一样发送WM_VSCROLL & WM_HSCROLL
WM_VSCROLL & WM_HSCROLL 参数lParam 为0则为窗口滚动条,否则为滚动条控件句柄。

Window核心编程相关推荐

  1. 将VC++6.0的代码迁移到VS2005常见问题总结(Window核心编程第五版以前代码在VS2005无法编译的解决方案)...

    额喜新厌旧是男人的通病吧,可是呢VS2005的界面看着的确比VC6.0看着舒服,而且也算用习惯了吧.可是网上现在大部分C/C++的代码还是用VC6.0的.这为我们这些菜鸟的学习之路增添了不少障碍,可能 ...

  2. 内存映射文件——Windows核心编程学习手札之十七

    内存映射文件 --Windows核心编程学习手札之十七 与虚拟内存一样,内存映射文件保留地址空间,并将物理存储器提交给该区域,差别在于所提交的物理存储器是磁盘上有文件存在的空间,而非系统的页文件,一旦 ...

  3. 线程的堆栈——Windows核心编程学习手札之十六

    线程的堆栈 --Windows核心编程学习手札之十六 系统会在进程的地址空间内保存一些区域,同时也会在进程地址空间内为线程的堆栈保留区域.线程都有自己的堆栈,创建时,系统就保留一个堆栈空间区域,并将相 ...

  4. 我对windows核心编程的理解之一

    看了几天windows核心编程VC++,前几天对进程,作业,线程的关系很迷惑,还有就是内核对象的应用也很迷茫.昨天自己拿着书,又翻过去看看.突然有一点心得,初步对windows下的三种工作单位有了新的 ...

  5. python核心编程--笔记(不定时跟新)(转)

    的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找python路径 1.4 –v   ...

  6. Windows核心编程 - API HOOK应用

    #Windows核心编程 - API HOOK应用 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 目录 文章目录 #Windows核 ...

  7. Spring Boot 核心编程思想-第一部分-读书笔记

    怕什么真理无穷 进一步有近一步的欢喜 说明 本文是Spring Boot核心编程思想记录的笔记,书籍地址:Spring Boot编程思想(核心篇): 本书已经简单读过一遍,在第一遍读的时候发现里面有些 ...

  8. C++Windows核心编程读书笔记(转)

    http://www.makaidong.com/(马开东博客) 这篇笔记是我在读<windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的 ...

  9. C++核心编程(一)

    C++ 核心编程 本系类列博客都是根据黑马的C++视频做的笔记. 本阶段主要针对C++面向对象编程技术做详细记录,探讨C++中的核心和精髓. 1.内存分区模型 C++程序在执行时,将内存大方向划分为4 ...

最新文章

  1. 如何在Ubuntu和CentOS上启用Nginx的HTTP/2 协议支持
  2. Oracle Sequence
  3. 秦汉考场科目三路线图_海淀驾校科目三校内考场总结
  4. 赞!图像生成PyTorch库火了,涵盖18+ SOTA GAN实现
  5. add_axes()——python绘图
  6. 大数四则运算java(转)
  7. 三维重建_对比几个三维重建系统(大部分开源)
  8. pg 简单备份和恢复
  9. 软件公司所犯的3种最严重的营销错误,你应该来看看
  10. linux怎么安装台式无线网卡,linux下安装无线网卡
  11. 推荐搜索的冷启动问题
  12. 科沃斯扫地机器人哪个型号最实用_科沃斯扫地机哪个型号好 三个价位三种选择...
  13. matplotlib绘制折线图的柱状图
  14. 上位机和三菱FN2x通信实例
  15. 互联网日报 | 贾跃亭乐视网股票流拍;东航组建“三亚国际航空”;苹果线上WWDC大会22日举办...
  16. 快给你的对象做一个微信公众号播报吧-java版
  17. js查找数组中符合条件的元素
  18. android framework-zygote进程
  19. html标签 ppt,HTML框架标签、超链接标签、控件标签.ppt
  20. IQOO换鸿蒙系统,1998 iQOO 845版明天发?| 华为自研系统鸿蒙在全球注册商标

热门文章

  1. Python语言学习之文件格式后缀那些事:python和常见各种文件格式后缀介绍、使用方法之详细攻略
  2. HighNewTech之5G网络:带你了解5G网络的前世今生—两张长图帮你捋清思路
  3. DL之GoogleNet:GoogleNet(InceptionV1)算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  4. 理解 java 中常用数据结构
  5. 在Javascript中 声明时用var与不用var的区别,== 和 ===的区别
  6. 阅读《Oracle内核技术揭秘》的读书笔记
  7. jquery,angular 对象数组的克隆和深度克隆
  8. VJ 1033 整数分解(版本2)
  9. [唐胡璐]Java操作Sql Server 2008数据库
  10. Maven报错“未结束的字符串字面值”