窗口控件
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInstance = NULL; // 通常这里不需要static,但如果您想在WM_CREATE之外获取它,可以这样做
switch (msgID)
{
case WM_CREATE:
hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); // 获取当前实例句柄
CreateWindowW(L"BUTTON", L"按钮1", WS_CHILD | WS_VISIBLE, 100, 100, 80, 50, hWnd, (HMENU)ID_BUTTON1, hInstance, NULL);
CreateWindowW(L"BUTTON", L"移动窗口", WS_CHILD | WS_VISIBLE, 190, 100, 80, 50, hWnd, (HMENU)ID_BUTTON2, hInstance, NULL);
CreateWindowW(L"BUTTON", L"获取文本框内容", WS_CHILD | WS_VISIBLE, 280, 100, 120, 50, hWnd, (HMENU)ID_BUTTON3, hInstance, NULL);
CreateWindowW(L"BUTTON", L"文本框内容", WS_CHILD | WS_VISIBLE, 300, 200, 120, 50, hWnd, (HMENU)ID_BUTTON4, hInstance, NULL);
CreateWindowW(L"BUTTON", L"设置父窗口", WS_CHILD | WS_VISIBLE, 150, 150, 80, 50, hWnd, (HMENU)ID_BUTTON5, hInstance, NULL);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
WORD ctrlid = LOWORD(wParam);
int x, y = 0;
switch (ctrlid)
{
case ID_BUTTON1:
MessageBox(hWnd, "按钮1被点击了", "信息", MB_OK);
break;
case ID_BUTTON2:
RECT rect;
GetClientRect(hWnd, &rect); // 注意:这将获取客户区的大小,而不是整个窗口
x = rand() % (rect.right - 80);
y = rand() % (rect.bottom - 50);
MoveWindow((HWND)lParam, x, y, 80, 50, TRUE);
break;
case ID_BUTTON3:
WCHAR buff[100]{ 0 };
MessageBox(hWnd, "设置文本框内容的按钮被点击了,但这里没有文本框", "信息", MB_OK);
HWND IDBT = GetDlgItem(hWnd, ID_BUTTON4);
GetWindowText(IDBT, (LPSTR)buff, 100);
MessageBoxW(hWnd, buff, L"haa", MB_OK);
break;
case ID_BUTTON5:
SetParent((HWND)lParam, (HWND)0x00010D74);
break;
资源利用
HCURSOR hcursor = LoadCursor(hInstance, LPCSTR(IDC_CURSOR1));
GetClassLongW(hWnd, GCL_HCURSOR, (LONG)hcursor);
wc.hCursor = LoadCursor(0, MAKEINTRESOURCE(IDC_CURSOR1));
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
对话框
#include<Windows.h>
#include <stdio.h>
#include <CommCtrl.h>
#include "resource.h"
INT_PTR CALLBACK Dlgproc
(
HWND hWnd,
UINT Umsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (Umsg)
{
case WM_INITDIALOG:
{
MessageBoxW(hWnd, L"创建成功", L"提示", MB_OK);
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
PostQuitMessage(0);
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 0x10:
MessageBoxW(hWnd, L"BUTTON1", L"提示", MB_OK);
break;
case 0x20:
MessageBoxW(hWnd, L"BUTTON2", L"提示", MB_OK);
break;
}
default: {
return FALSE;
}
}
return TRUE;
}
int WINAPI WinMain
(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
)
{
HWND hWnd = CreateDialogW(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, Dlgproc);
ShowWindow(hWnd, SW_SHOWNORMAL);
MSG msg{ 0 };
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
#include <CommCtrl.h>
#include "resource.h"
INT_PTR CALLBACK Dlgproc
(
HWND hWnd,
UINT Umsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (Umsg)
{
case WM_INITDIALOG:
{
MessageBoxW(hWnd, L"创建成功", L"提示", MB_OK);
break;
}
case WM_CLOSE:
{
EndDialog(hWnd, 0);
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 0x10:
MessageBoxW(hWnd, L"BUTTON1", L"提示", MB_OK);
break;
case 0x20:
MessageBoxW(hWnd, L"BUTTON2", L"提示", MB_OK);
break;
}
default: {
return FALSE;
}
}
return TRUE;
}
int WINAPI WinMain
(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
)
{
DialogBoxW(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, Dlgproc);
return 0;
}
点击按钮
Button_SetCheck((HWND)IDD_DIALOG1, BST_UNCHECKED);
下拉框
ComboBox_AddString(GetDlgItem(hwnd, IDC_COMBO1), L"选项1");
ComboBox_AddString(GetDlgItem(hwnd, IDC_COMBO1), L"选项2");
进度条控制
INT_PTR CALLBACK Dlgproc(
HWND hwnd,
UINT Umsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (Umsg)
{
case WM_INITDIALOG:
SendDlgItemMessageW(hwnd, IDC_PROGRESS1, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
SendDlgItemMessageW(hwnd, IDC_SLIDER1, TBM_SETRANGE, TRUE, MAKELPARAM(0, 100));
break;
case WM_CLOSE:
EndDialog(hwnd, 0);
break;
case WM_COMMAND:
break;
case WM_HSCROLL:
if (GetDlgItem(hwnd, IDC_SLIDER1) == (HWND)lParam)
{
int Pos = SendMessageW((HWND)lParam, TBM_GETPOS, 0, 0);
SendDlgItemMessageW(hwnd, IDC_PROGRESS1, PBM_SETPOS, Pos, 0);
}
break;
default:
return FALSE;
}
return TRUE;
}
动态链接库
cpp
#include "main.h"
typedef int (*func)(int a, int b);
int main()
{
HMODULE hMOULE = LoadLibrary(L"MY_DLL.dll");
func fun = (func)GetProcAddress(hMOULE, "func");
printf("%d", fun(1, 2));
return 0;
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
int func(int a, int b)
{
return a + b;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
h
#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
extern "C" _declspec(dllexport) int func(int a, int b);
void Cmy_button::OnBnClicked()
//控件子窗口来处理消息 由于c++是通过对象来处理事件的,所以我们点击按钮需要通过创建按钮对象来实现
{
// TODO: 在此添加控件通知处理程序代码
MessageBox(L"子窗口控件处理"); //同时对于子窗口处理了的事件,父窗口将不会再一次进行处理
}
MFC的button窗户变换
void Cmy_button::OnBnClicked()
//控件子窗口来处理消息 由于c++是通过对象来处理事件的,所以我们点击按钮需要通过创建按钮对象来实现
{
CRect fe{ 0 };
CRect bu{ 0 };
GetParent()->GetClientRect(fe);
GetClientRect(bu);
int x = rand() % (fe.Height() - bu.Height());
int y = rand() % (fe.Width() - bu.Width());
bu.MoveToXY(x, y);
MoveWindow(bu);
}
通过点击获取单选框内容
void Cmy_Dialog::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString strbuff;
UpdateData();
GetDlgItemText(IDC_RADIO1 + m_radio, strbuff);
MessageBox(strbuff);
}
内核:
进程基础操作
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
int main()
{
//打开一个进程
HANDLE QQmusic = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 22608);
//结束一个进程
TerminateProcess(QQmusic, 0);
//遍历进程快照
/*
PROCESSENTRY32W processEntry32 = { sizeof(PROCESSENTRY32W) };
HANDLE hprocess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL re = Process32First(hprocess, &processEntry32);
if (re)
{
do
{
printf("进程ID=%d,进程名称=%ls\n", processEntry32.th32ProcessID, processEntry32.szExeFile);
} while (Process32NextW(hprocess, &processEntry32));
}
*/
//模块
MODULEENTRY32 moduleEntry32 = { sizeof(MODULEENTRY32) };
HANDLE hprocess = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 29876);
BOOL re = Module32FirstW(hprocess, &moduleEntry32);
if (re)
{
do
{
printf("进程名称 = % ls\n", moduleEntry32.szExePath);
} while (Module32NextW(hprocess, &moduleEntry32));
}
return 0;
}
进程间通信:
进程间通信实现的就是在独立的一个进程中实现不同进程的交互过程
这里我们通过创建一个进程来实现找到我们的另一个进程,并实现我们另一个进程的获取创建进程的消息内容
发送消息进程:
#include <Windows.h>
int main()
{
HWND findWND = FindWindowW(NULL, L"chen");
COPYDATASTRUCT copydate = { 0 };
copydate.lpData = (LPVOID)L"发送成功";
copydate.cbData = 10;
SendMessageW(findWND, WM_COPYDATA, NULL, (LPARAM)©date);
return 0;
}
通过发送进程来获取消息
#include <Windows.h>
#include"resource.h"
INT_PTR CALLBACK WinProc(
HWND hwnd,
UINT msg,
WPARAM wPararm,
LPARAM LPARAM
)
{
PCOPYDATASTRUCT pCopyDate = (PCOPYDATASTRUCT)LPARAM;
switch (msg)
{
case WM_COPYDATA:
MessageBoxW(hwnd, (LPCWSTR)pCopyDate->lpData, L"提示", MB_OK);
break;
case WM_CLOSE:
EndDialog(hwnd, 0);
break;
default:
return FALSE;
}
return TRUE;
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrestance,
LPSTR lpCmdLine,
int nShowCmd
)
{
DialogBoxW(hInstance, (LPCWSTR)MAKEINTRESOURCE(IDD_DIALOG1), NULL, WinProc);
return 0;
}
或者通过邮筒的形式mailslot利用先创建一个邮筒,然后通过邮筒接收邮件file,然后通过发送方发送邮递的形式发送邮件,从而使用我们的进程之间的内容交互
发送方:
#include <Windows.h>
int main()
{
HANDLE mailsolt = CreateFile(L"\\\\.\\mailslot\\Chen", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (mailsolt == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, L"错误的句柄", L"提示", MB_OK);
return FALSE;
}
WCHAR buff[] = L"chen";
DWORD sz;
WriteFile(mailsolt, buff, 6, &sz, NULL);
CloseHandle(mailsolt);
return 0;
}
接收方:
#include <Windows.h>
int main()
{
HANDLE hMainslot = CreateMailslot(L"\\\\.\\mailslot\\Chen", 100, MAILSLOT_WAIT_FOREVER, NULL);
if (hMainslot == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, L"错误的句柄", L"提示", MB_OK);
return FALSE;
}
WCHAR buff[50]{ 0 };
DWORD readSize;
ReadFile(hMainslot, buff, 100, &readSize, NULL);
MessageBoxW(0, buff, L"提示", MB_OK);
CloseHandle(hMainslot);
return 0;
}
线程
进程是分配资源的单位,线程是执行程序操作的单位,一个进程至少有一个线程来执行操作
同时主线程和次线程之间属于并行的结果,执行过程中是保持平等的,但是主线程结束之后会使得子线程无法进行
#include <Windows.h>
#include <iostream>
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
)
{
printf("回调函数执行了");
return 0;
};
int main()
{
HANDLE hThead = CreateThread(NULL, NULL, ThreadProc, 0, 0, NULL);
while (1)
{
printf("线程");
}
return 0;
}
由于我们的线程是并行的,所有主线程存在多久,子线程就会执行多久
#include <Windows.h>
#include <iostream>
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
)
{
while (1)
{
printf("回调函数");
}
return 0;
} ;
int main()
{
HANDLE hThead = CreateThread(NULL, NULL, ThreadProc, 0, 0, NULL);
Sleep(2222);
// WaitForSingleObject(hThead, -1);
return 0;
}
//这里的2222毫秒之间都会一直的打印“回调函数”
WaitForSingleObject(hThead, -1); waitforsingleobject函数是当满足传入的句柄的线程执行完成之后才会进入下一步
这样就可以通过子线程去控制主线程的时间了
打开并关闭线程
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
)
{
int i = 0;
while (i < 100)
{
printf("回调函数");
i++;
}
return 0;
};
int main()
{
HANDLE hThreadList = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 threadInfo{ sizeof(THREADENTRY32) };
BOOL issucess = Thread32First(hThreadList, &threadInfo);
if (issucess)
{
do
{
if (threadInfo.th32OwnerProcessID == 23672)
{
printf("线程ID:%d\n", threadInfo.th32ThreadID);
HANDLE thread1 = OpenThread(THREAD_ALL_ACCESS, NULL, threadInfo.th32ThreadID);
SuspendThread(thread1);
}
} while (Thread32Next(hThreadList, &threadInfo));
}
return 0;
}
线程同步:
相同的线程程序,可能执行次数是不同的,由于进程分配的资源有限的同时,cup的执行过程可能也会存在问题,会导致对同一个变量的相同操作执行出不同的结果
#include <Windows.h>
#include <iostream>
size_t g_count = 0;
DWORD WINAPI ThreadProc1(
_In_ LPVOID lpParameter
)
{
for (size_t i = 0; i < 100000; i++)
{
g_count++;
}
return 0;
}
DWORD WINAPI ThreadProc2(
_In_ LPVOID lpParameter
)
{
for (size_t i = 0; i < 100000; i++)
{
g_count++;
}
return 0;
}
int main()
{
HANDLE Tread1 = CreateThread(NULL, 100, ThreadProc1, NULL, 0, NULL);
HANDLE Tread2 = CreateThread(NULL, 100, ThreadProc2, NULL, 0, NULL);
WaitForSingleObject(Tread1, INFINITE);
WaitForSingleObject(Tread1, INFINITE);
printf("%d", g_count);
return 0;
}
/*方法:
1. 我们可以使用InterlockedIncrement(&g_count);将变量锁入临界区再cup一一处理之后再让另外的线程使用临界区资源
2. 我们直接创建临界区,让一个个线程通过临界区去执行代码
for (size_t i = 0; i < 100000; i++)
{
EnterCriticalSection(&Critical_area);
g_count++;
LeaveCriticalSection(&Critical_area);
}
return 0;
*/
线程之间的执行情况是不同了,不同的线程可能每次执行的顺序也不一样
#include <Windows.h>
#include <iostream>
size_t g_count = 0;
HANDLE hEvent;
CRITICAL_SECTION Critical_area{ 0 };
DWORD WINAPI ThreadProc1(
_In_ LPVOID lpParameter
)
{
printf("线程一");
return 0;
}
DWORD WINAPI ThreadProc2(
_In_ LPVOID lpParameter
)
{
printf("线程二");
return 0;
}
DWORD WINAPI ThreadProc3(
_In_ LPVOID lpParameter
)
{
printf("线程三");
return 0;
}
int main()
{
InitializeCriticalSection(&Critical_area);
HANDLE Tread1 = CreateThread(NULL, 100, ThreadProc1, NULL, 0, NULL);
HANDLE Tread2 = CreateThread(NULL, 100, ThreadProc2, NULL, 0, NULL);
HANDLE Tread3 = CreateThread(NULL, 100, ThreadProc3, NULL, 0, NULL);
WaitForSingleObject(Tread1, -1);
WaitForSingleObject(Tread2, -1);
WaitForSingleObject(Tread3, -1);
DeleteCriticalSection(&Critical_area);
return 0;
}//线程一二三先执行都有可能
event
这时我们就可以使用Event这个数据结构来实现,它没有确定临界区的归属,也就是说,事件Event1锁上的临界区,其他临界区也可以去打开,这样我们可以去调控顺序
#include <Windows.h>
#include <iostream>
size_t g_count = 0;
HANDLE hEvent1;
HANDLE hEvent2;
HANDLE hEvent3;
CRITICAL_SECTION Critical_area{ 0 };
DWORD WINAPI ThreadProc1(
_In_ LPVOID lpParameter
)
{
WaitForSingleObject(hEvent1, -1);
printf("线程一");
SetEvent(hEvent2);
return 0;
}
DWORD WINAPI ThreadProc2(
_In_ LPVOID lpParameter
)
{
WaitForSingleObject(hEvent2, -1);
printf("线程二");
SetEvent(hEvent3);
return 0;
}
DWORD WINAPI ThreadProc3(
_In_ LPVOID lpParameter
)
{
WaitForSingleObject(hEvent3, -1);
printf("线程三");
return 0;
}
int main()
{
hEvent1 = CreateEventW(NULL, FALSE, FALSE, L"one");
hEvent2 = CreateEventW(NULL, FALSE, FALSE, L"two");
hEvent3 = CreateEventW(NULL, FALSE, FALSE, L"three");
SetEvent(hEvent1);
InitializeCriticalSection(&Critical_area);
HANDLE Tread1 = CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
HANDLE Tread2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
HANDLE Tread3 = CreateThread(NULL, 0, ThreadProc3, NULL, 0, NULL);
WaitForSingleObject(Tread1, -1);
WaitForSingleObject(Tread2, -1);
WaitForSingleObject(Tread3, -1);
DeleteCriticalSection(&Critical_area);
return 0;
}//这里我们通过Event事件通过控制信号状态使得,先让Event1事件先为信号状态,同步的过程执行完ThreadProc1,然后再setEvent为event2执行二,同理执行三
异步IO
同步IO,当我们读取一个文件时,一般情况下,线程是阻塞的,也就是说,需要当前的线程等待文件读取操作成功并且结束之后再进行下一步的操作(阻塞程序),这种叫做同步IO。
异步IO则是在用户读取文件的时候不会阻塞线程的进行,而是交给系统底层自动去处理读取文件,这样文件的读取就不会去阻塞线程的进行。
//异步读取文件
#include <Windows.h>
#include<iostream>
int main()
{
HANDLE hFile = CreateFileW(L"game.txt", GENERIC_ALL, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
WCHAR buff[100]{ 0 };
OVERLAPPED overlapped{ 0 };//lapped 重叠
ReadFile(hFile, buff, 0x100, NULL, &overlapped);
DWORD num_read;
WaitForSingleObject(hFile, -1);
GetOverlappedResult(hFile, &overlapped, &num_read, TRUE);
printf("内容%s", buff);
printf("长度%d", buff);
return 0;
}
APC:
每一个线程都维护了一个APC队列,队列中的每一项都是一个函数,当线程处于闲暇状态时,线程会去遍历我们的APC队列,然后去调用所有函数,直到结束,再恢复执行。
//上面的代码虽然可以实现我们的异步IO,但是都没有真正的逃过临界区的等待,比如WaitForSingleObject(hFile, -1)....那我们应该怎么办才能真正的实现这一个操作呢?那就是通过回调函数,让函数直接告诉我们文件读取成功了,然后再进行下一步,所以windows有响应的API去实现我们的这一个情况
#include <Windows.h>
#include<iostream>
void WINAPI lpOverLapped_completion_Proc(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
)
{
printf("dadadadad");
}
int main()
{
HANDLE hFile = CreateFile(L"game.txt", GENERIC_ALL, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
char buff[100]{ 0 };
OVERLAPPED overapped{ 0 };
//overapped.hEvent = CreateEventW(NULL, FALSE, FALSE, L"chen");//通过将hFile转为Event来实现判断文件的读取是否完成
ReadFileEx(hFile, buff, 0x100, &overapped, lpOverLapped_completion_Proc);
DWORD real_num;
GetOverlappedResult(hFile, &overapped, &real_num, TRUE);
printf("%s", buff);
return 0;
}
标签:case,NULL,return,windows,int,线程,include
From: https://www.cnblogs.com/ovo-fisherman/p/18220671