日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Window核心编程

發布時間:2025/3/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Window核心编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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核心编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。