├── .gitignore ├── 01. hello windows.c ├── 02. touch.c ├── 03. rm.c ├── 04. cp.c ├── 05. mv.c ├── 06. ls.c ├── 07. lscmd ├── 1.c ├── 2.c └── 3.c ├── 08. ps.c ├── 09. kill.c ├── 10. threadTest.c ├── 11. snake.c ├── 12. TestDLL ├── DLLTEST │ ├── dll.h │ └── main.c └── LoadDLL │ └── main.c ├── 13. CreateWindow.c ├── 14. KeyBoardHook.c ├── 15. MouseHook.c ├── 16. hotkey_console.c ├── 17. hotkey_window.c ├── 18. hotkey_complex.c ├── 19. Scoket example ├── TCP_SCOKET_CLIENT_TEST │ ├── TCP_SCOKET_CLIENT_TEST.sln │ ├── TCP_SCOKET_CLIENT_TEST.suo │ └── TCP_SCOKET_CLIENT_TEST │ │ ├── TCP_SCOKET_CLIENT_TEST.vcxproj │ │ ├── TCP_SCOKET_CLIENT_TEST.vcxproj.filters │ │ ├── TCP_SCOKET_CLIENT_TEST.vcxproj.user │ │ └── client.c ├── TCP_SOCKET_SERVER_TEST │ ├── TCP_SOCKET_SERVER_TEST.sln │ ├── TCP_SOCKET_SERVER_TEST.suo │ └── TCP_SOCKET_SERVER_TEST │ │ ├── TCP_SOCKET_SERVER_TEST.vcxproj │ │ ├── TCP_SOCKET_SERVER_TEST.vcxproj.filters │ │ ├── TCP_SOCKET_SERVER_TEST.vcxproj.user │ │ └── server.c ├── TCP_Scoket_Client.zip └── TCP_Socket_Server.zip ├── LICENSE ├── README.md └── port ├── port.sln ├── port.suo └── port ├── port.c ├── port.vcxproj ├── port.vcxproj.filters └── port.vcxproj.user /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | 34 | *.zip 35 | 36 | *.zip 37 | -------------------------------------------------------------------------------- /01. hello windows.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | MessageBox(NULL, (LPCSTR)"hello, windows programming", (LPCSTR)"Title", MB_OK); 6 | return 0; 7 | } 8 | 9 | /* 10 | 如果使用 vc6.0 出现 windows.h 未找到之类的错误 11 | 可以考虑下载完整版或者是加强版的vc6 12 | 地址:http://hi.baidu.com/jsj08/item/fa8ac4c44aafa22947d5c046 13 | 14 | 当然使用 visual studio 2010 及以上版本也不错 15 | */ -------------------------------------------------------------------------------- /02. touch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for printf 3 | void help(); 4 | 5 | int main(int argc, char const *argv[]) 6 | { 7 | int i; 8 | 9 | // 参数数目为1 即用户只输入程序名,程序仅收到一个参数 10 | if (argc == 1) 11 | { 12 | help(); 13 | return 0; 14 | } 15 | 16 | // 遍历指针数组所指向的参数 17 | for (i = 1; i < argc; i++) 18 | { 19 | CreateFile( 20 | argv[i], // 文件名 21 | GENERIC_WRITE, // 写入权限 22 | 0, // 阻止其他进程访问 23 | NULL, // 子进程不可继承本句柄 24 | CREATE_NEW, // 仅不存在时创建新文件 25 | FILE_ATTRIBUTE_NORMAL, // 普通文件 26 | NULL); // 不适用模板文件 27 | } 28 | 29 | 30 | return 0; 31 | } 32 | 33 | void help() 34 | { 35 | printf("创建新文件:"); 36 | printf("touch <文件名1> <文件名2> ..."); 37 | } -------------------------------------------------------------------------------- /03. rm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for printf 3 | 4 | #define FILE_DEL_MAX 10 5 | 6 | void help(); 7 | 8 | struct _del_attr { 9 | int Force_del; // 强制删除选项 10 | } ; 11 | 12 | struct _del_list { 13 | const char *File_to_Del[FILE_DEL_MAX]; // 待删文件列表 14 | int count; // 待删文件数量 15 | struct _del_attr Attr; // 删除选项 16 | } Delete_list = {0}; 17 | 18 | int main(int argc, const char *argv[]) 19 | { 20 | int i; 21 | char cmd; 22 | 23 | if(argc == 1) 24 | { 25 | help(); 26 | } 27 | 28 | // 遍历参数 29 | for (i = 1; i < argc; i++) 30 | { 31 | // 获取参数选项 32 | if( *argv[i] == '-') // 如果当前指向字符串的第一个为 '-' 33 | { 34 | if( strcmp( argv[i], "-f" ) == 0 ) 35 | { 36 | Delete_list.Attr.Force_del = 1; 37 | } 38 | } else // 保存文件路径 39 | { 40 | Delete_list.File_to_Del[Delete_list.count] = argv[i]; 41 | // printf("待删文件路径 [%s] 已保存\n", Delete_list.File_to_Del[Delete_list.count]); 42 | Delete_list.count++; 43 | // printf("目前待删文件数目 %d\n", Delete_list.count); 44 | } 45 | } 46 | 47 | // 遍历待删文件列表 48 | for (i = 0; i < Delete_list.count; i++) 49 | { 50 | if( Delete_list.Attr.Force_del == 1 ) // 是否强制删除 51 | { 52 | if( !DeleteFile( Delete_list.File_to_Del[i] ) ) // 如果非零则删除失败 53 | { 54 | printf("删除文件错误:%x\n",GetLastError()); 55 | } 56 | }else 57 | { // 询问是否删除 58 | printf("是否要删除文件 [%s] ?(y/n)", Delete_list.File_to_Del[i] ); 59 | scanf("%c", &cmd); 60 | getchar(); // 回收回车 61 | if ( cmd == 'y' ) 62 | { 63 | if( !DeleteFile( Delete_list.File_to_Del[i] ) ) // 如果非零则删除失败 64 | { 65 | printf("删除文件错误:%x\n",GetLastError()); 66 | }else 67 | { 68 | printf("文件 [%s] 已删除\n", Delete_list.File_to_Del[i]); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | void help() 76 | { 77 | printf("删除文件:\n"); 78 | printf("rm <文件名1> <文件名2> ... [-选项]\n"); 79 | printf("选项: -f 强制删除"); 80 | } -------------------------------------------------------------------------------- /04. cp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for printf 3 | #include // for string operation 4 | 5 | int isDirectory(char *path); 6 | void help(); 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | char file_src[MAX_PATH]={0}; 11 | char file_dest[MAX_PATH]={0}; 12 | 13 | // 只输入程序名 和一个参数则调用help 14 | if (argc <= 2) 15 | { 16 | help(); 17 | return 0; 18 | } 19 | 20 | memmove(file_src, argv[1], strlen(argv[1])); 21 | memmove(file_dest, argv[2], strlen(argv[2])); 22 | 23 | if( isDirectory(file_dest) ) 24 | { // 如果第二个参数是目录, 则拼装新的文件路径 25 | sprintf(file_dest, "%s\\%s", file_dest, file_src); 26 | } 27 | 28 | if( CopyFile(file_src, file_dest, 0) == 0) 29 | printf("文件复制失败!"); 30 | 31 | return 0; 32 | } 33 | 34 | // 判断是否为目录 35 | BOOL isDirectory(char *path) 36 | { 37 | WIN32_FIND_DATA fd; 38 | BOOL rel = FALSE; 39 | char *p = path; 40 | 41 | // 查找到第一个文件的句柄 42 | HANDLE hFind = FindFirstFile(path, &fd); 43 | 44 | while(*p != '\0') p++; 45 | 46 | // 如果结尾是这两种符号就肯定是目录 47 | if( *(--p) == '\\' || *(p) == '/' ) { 48 | *p = '\0'; 49 | return TRUE; 50 | } 51 | 52 | // 判断是否获取错误 53 | if(hFind != INVALID_HANDLE_VALUE) 54 | { 55 | // 文件信息按位与上目录属性, 非目录则全部置零 56 | if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) 57 | { 58 | rel = TRUE; 59 | } 60 | // 关闭查找句柄 61 | FindClose(hFind); 62 | } 63 | return rel; 64 | } 65 | 66 | void help() 67 | { 68 | printf("复制文件:\n"); 69 | printf("cp <文件名> <新路径>\n"); 70 | printf("cp <文件名> <新文件名>\n"); 71 | printf("cp <文件名> <新路径\\新文件名>"); 72 | } -------------------------------------------------------------------------------- /05. mv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for printf 3 | #include // for string operation 4 | 5 | int isDirectory(char *path); 6 | void help(); 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | char file_src[MAX_PATH]={0}; 11 | char file_dest[MAX_PATH]={0}; 12 | 13 | // 只输入程序名 和一个参数则调用help 14 | if (argc <= 2) 15 | { 16 | help(); 17 | return 0; 18 | } 19 | 20 | memmove(file_src, argv[1], strlen(argv[1])); 21 | memmove(file_dest, argv[2], strlen(argv[2])); 22 | 23 | if( isDirectory(file_dest) ) 24 | { // 如果第二个参数是目录, 则拼装新的文件路径 25 | sprintf(file_dest, "%s\\%s", file_dest, file_src); 26 | } 27 | 28 | if( MoveFile(file_src, file_dest) == 0) 29 | printf("文件剪切失败!"); 30 | 31 | return 0; 32 | } 33 | 34 | // 判断是否为目录 35 | BOOL isDirectory(char *path) 36 | { 37 | WIN32_FIND_DATA fd; 38 | BOOL rel = FALSE; 39 | char *p = path; 40 | 41 | // 查找到第一个文件的句柄 42 | HANDLE hFind = FindFirstFile(path, &fd); 43 | 44 | while(*p != '\0') p++; 45 | 46 | // 如果结尾是这两种符号就肯定是目录 47 | if( *(--p) == '\\' || *(p) == '/' ) { 48 | *p = '\0'; 49 | return TRUE; 50 | } 51 | 52 | // 判断是否获取错误 53 | if(hFind != INVALID_HANDLE_VALUE) 54 | { 55 | // 文件信息按位与上目录属性, 非目录则全部置零 56 | if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) 57 | { 58 | rel = TRUE; 59 | } 60 | // 关闭查找句柄 61 | FindClose(hFind); 62 | } 63 | return rel; 64 | } 65 | 66 | void help() 67 | { 68 | printf("剪切文件:\n"); 69 | printf("mv <文件名> <新路径>\n"); 70 | printf("mv <文件名> <新文件名>\n"); 71 | printf("mv <文件名> <新路径\\新文件名>"); 72 | } -------------------------------------------------------------------------------- /06. ls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for sprintf 3 | #include // for memmove 4 | 5 | int main(int argc, const char *argv[]) 6 | { 7 | CHAR path[MAX_PATH] = {0}; // 待列路径 8 | CHAR szFilePath[MAX_PATH]; // 具体查找路径 9 | HANDLE hListFile; // 获取到的文件句柄 10 | WIN32_FIND_DATA fileData; // 查找到的文件数据 11 | 12 | 13 | if(argc == 1) // 只输入程序名则显示当前目录 14 | { 15 | GetCurrentDirectory(MAX_PATH,path); 16 | }else if(argc == 2) // 指定显示目录则显示指定目录 17 | { 18 | memmove(path, argv[1], strlen(argv[1])); 19 | } 20 | 21 | // 复制路径到具体查找路径 22 | lstrcpy(szFilePath, path); 23 | // 路径拼接通配符 24 | lstrcat(szFilePath, "\\*"); 25 | 26 | // printf("列表路径: [%s] \n", szFilePath); 27 | 28 | // 查找路径下第一个文件/目录,获得句柄 29 | hListFile = FindFirstFile(szFilePath,&fileData); 30 | 31 | // 判断句柄是否获取到 32 | if(hListFile == INVALID_HANDLE_VALUE) 33 | { 34 | printf("错误:%d",GetLastError()); 35 | return 1; 36 | } else { 37 | do 38 | { // 输出找到的文件名 39 | printf("%s\t", fileData.cFileName ); 40 | } // 查找下一个文件, 并获取其信息 41 | while(FindNextFile(hListFile, &fileData)); 42 | } 43 | return 0; 44 | } -------------------------------------------------------------------------------- /07. lscmd/1.c: -------------------------------------------------------------------------------- 1 | 2 | 3 3 | 4 4 | 5 5 | 6 6 | 7 7 | 8 8 | 9 9 | 10 10 | 11 11 | 12 12 | 13 13 | 14 14 | 15 15 | 16 16 | 17 17 | 18 18 | 19 19 | 20 20 | 21 21 | 22 22 | 23 23 | 24 24 | 25 25 | 26 26 | 27 27 | 28 28 | 29 29 | 30 30 | 31 31 | 32 32 | 33 33 | 34 34 | 35 35 | 36 36 | 37 37 | 38 38 | 39 39 | 40 40 | #include ; 41 | #include ; 42 | 43 | void welcome(); 44 | 45 | int main() 46 | { 47 | char Command_str[MAX_PATH]; 48 | DWORD Command_len; 49 | HANDLE hConsoleInput; 50 | 51 | // 获取输出流的句柄 52 | hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); 53 | 54 | // 输出欢迎信息 55 | welcome(); 56 | 57 | while(1) 58 | { 59 | // 清空命令字符串 60 | memset(&Command_str, 0, MAX_PATH); 61 | // 输出提示符 62 | printf("\nLscmd>;"); 63 | // 读取输入流 64 | ReadFile( 65 | hConsoleInput, // 文件句柄 66 | Command_str, // 获取内容的缓冲字符数组 67 | MAX_PATH, // 缓冲数组大小 68 | &Command_len, // 实际读出的大小 69 | NULL); 70 | 71 | printf("接收到命令:[%s]", Command_str); 72 | } 73 | } 74 | 75 | void welcome() 76 | { 77 | printf("Lellansin's CMD Tool [版本 0.0.1]\n"); 78 | printf("学习自制 (c) www.lellansin.com 欢迎交流\n"); 79 | } -------------------------------------------------------------------------------- /07. lscmd/2.c: -------------------------------------------------------------------------------- 1 | #include ; 2 | #include ; 3 | #include ; // for strcmp 4 | #include ; // for exit 5 | 6 | void welcome(); 7 | void command_switch(char *cmd_str); 8 | 9 | int main() 10 | { 11 | char Command_str[MAX_PATH]; 12 | DWORD Command_len; 13 | HANDLE hConsoleInput; 14 | 15 | // 获取输出流的句柄 16 | hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); 17 | 18 | // 输出欢迎信息 19 | welcome(); 20 | 21 | while(1) 22 | { 23 | // 清空命令字符串 24 | memset(&Command_str, 0, MAX_PATH); 25 | // 输出提示符 26 | printf("\nLscmd>;"); 27 | // 读取输入流 28 | ReadFile( 29 | hConsoleInput, // 文件句柄 30 | Command_str, // 获取内容的缓冲字符数组 31 | MAX_PATH, // 缓冲数组大小 32 | &Command_len, // 实际读出的大小 33 | NULL); 34 | 35 | command_switch(Command_str); 36 | } 37 | } 38 | 39 | void command_switch(char *cmd_str) 40 | { 41 | char cmd_tmp[MAX_PATH]={0}; 42 | char *pstr = cmd_str, *ptmp = cmd_tmp; 43 | 44 | // 一直赋值到换行之前 45 | while(*pstr != '\r' && *pstr != '\n') 46 | { 47 | *ptmp++ = *pstr++; 48 | } 49 | // printf("收到命令:[%s]\n", cmd_tmp); 50 | 51 | // 判断命令 52 | if( strcmp(cmd_tmp, "hi") == 0 ) 53 | { 54 | printf("你好~"); 55 | } else if ( strcmp( cmd_tmp, "exit" ) == 0 ) 56 | { 57 | exit(0); 58 | }else 59 | { 60 | printf("Error: 命令未找到\n"); 61 | } 62 | } 63 | 64 | void welcome() 65 | { 66 | printf("Lellansin's CMD Tool [版本 0.0.1]\n"); 67 | printf("学习自制 (c) www.lellansin.com 欢迎交流\n"); 68 | } -------------------------------------------------------------------------------- /07. lscmd/3.c: -------------------------------------------------------------------------------- 1 | #include ; 2 | #include ; 3 | #include ; // for strcmp 4 | #include ; // for exit 5 | 6 | void welcome(); 7 | void command_switch(char *cmd_str); 8 | BOOL CreateChildProcess(char *cmd_str); 9 | 10 | int main() 11 | { 12 | char Command_str[MAX_PATH]; 13 | DWORD Command_len; 14 | HANDLE hConsoleInput; 15 | 16 | // 获取输出流的句柄 17 | hConsoleInput = GetStdHandle(STD_INPUT_HANDLE); 18 | 19 | // 输出欢迎信息 20 | welcome(); 21 | 22 | while(1) 23 | { 24 | // 清空命令字符串 25 | ZeroMemory(&Command_str, MAX_PATH); 26 | // 输出提示符 27 | printf("\nLscmd>;"); 28 | // 读取输入流 29 | ReadFile( 30 | hConsoleInput, // 文件句柄 31 | Command_str, // 获取内容的缓冲字符数组 32 | MAX_PATH, // 缓冲数组大小 33 | &Command_len, // 实际读出的大小 34 | NULL); 35 | 36 | command_switch(Command_str); 37 | } 38 | } 39 | 40 | void command_switch(char *cmd_str) 41 | { 42 | char *pstr = cmd_str; 43 | 44 | // 遍历到换行之前 45 | while(*pstr != '\r' && *pstr != '\n') 46 | { 47 | *pstr++; 48 | } 49 | // 覆盖换行 50 | *pstr = '\0'; 51 | // printf("收到命令:[%s]\n", cmd_str); 52 | 53 | // 判断命令 54 | if( strcmp(cmd_str, "hi") == 0 ) 55 | { 56 | printf("你好~ 欢迎使用 Lellansin 的cmd工具\n"); 57 | } else if ( strcmp( cmd_str, "exit" ) == 0 ) 58 | { 59 | exit(0); 60 | }else 61 | { 62 | // 创建子进程 63 | CreateChildProcess(cmd_str); 64 | } 65 | } 66 | 67 | BOOL CreateChildProcess(char *cmd_str) 68 | { 69 | STARTUPINFO start_info; 70 | PROCESS_INFORMATION process_info; 71 | BOOL flag; 72 | 73 | // 将启动信息结构清零 ( 相当于 memset 0, 不过效率更高 ) 74 | ZeroMemory( &start_info, sizeof(start_info) ); 75 | // 设置结构大小,cb属性应为结构的大小 76 | start_info.cb = sizeof(start_info); 77 | // 将进程信息结构清零 78 | ZeroMemory( &process_info, sizeof(process_info) ); 79 | 80 | flag = CreateProcess( 81 | NULL, // 不传程序路径, 使用命令行 82 | cmd_str, // 命令行命令 83 | NULL, // 不继承进程句柄(默认) 84 | NULL, // 不继承线程句柄(默认) 85 | FALSE, // 不继承句柄(默认) 86 | 0, // 没有创建标志(默认) 87 | NULL, // 使用默认环境变量 88 | NULL, // 使用父进程的目录 89 | &start_info, // STARTUPINFO 结构 90 | &process_info );// PROCESS_INFORMATION 保存相关信息 91 | 92 | if ( !flag ) 93 | { 94 | // 创建失败 95 | printf( "Error: 命令未找到 (%d).\n", GetLastError() ); 96 | return 0; 97 | } 98 | 99 | // 等待子进程结束 100 | // 使用到了通过 PROCESS_INFORMATION 结构体获取子进程的句柄 hProcess 101 | WaitForSingleObject( process_info.hProcess, INFINITE ); 102 | // 关闭进程句柄和线程句柄 103 | CloseHandle( process_info.hProcess ); 104 | CloseHandle( process_info.hThread ); 105 | 106 | return 1; 107 | } 108 | 109 | void welcome() 110 | { 111 | printf("Lellansin's CMD Tool [版本 0.0.1]\n"); 112 | printf("学习自制 (c) www.lellansin.com 欢迎交流\n"); 113 | } -------------------------------------------------------------------------------- /08. ps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | /* 6 | TlHelp32.h for 7 | PROCESSENTRY32 8 | CreateToolhelp32Snapshot() 9 | Process32First() 10 | Process32Next() 11 | */ 12 | 13 | int main(int argc, char const *argv[]) 14 | { 15 | HANDLE hSnapshot; 16 | HANDLE hProcess; 17 | PROCESSENTRY32 pe32; 18 | // 获取进程快照 19 | hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); 20 | if( hSnapshot == INVALID_HANDLE_VALUE ) 21 | { 22 | printf( "CreateToolhelp32Snapshot (of processes) 失败" ); 23 | return ; 24 | } 25 | // 设置输入参数,结构的大小 26 | pe32.dwSize = sizeof( PROCESSENTRY32 ); 27 | 28 | // 开始列举进程信息 29 | if( !Process32First( hSnapshot, &pe32 ) ) 30 | { 31 | printf( "Process32First() 失败" ); 32 | CloseHandle( hSnapshot ); // 关闭句柄 33 | return ; 34 | } 35 | 36 | printf("进程ID\t父进程\t线程数\t优先级\t进程名"); // 基本优先级 37 | do { 38 | // 打印进程相关信息 39 | printf( "\n%u", pe32.th32ProcessID ); // 进程id 40 | printf( "\t%u", pe32.th32ParentProcessID ); // 父进程id 41 | printf( "\t%d", pe32.cntThreads ); // 线程数 42 | printf( "\t%d", pe32.pcPriClassBase ); // 基本优先级 43 | printf( "\t%s", pe32.szExeFile ); // 进程名 44 | 45 | } while( Process32Next( hSnapshot, &pe32 ) ); 46 | 47 | CloseHandle( hSnapshot ); //关闭句柄 48 | 49 | return ; 50 | } -------------------------------------------------------------------------------- /09. kill.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void help(); 5 | 6 | int main(int argc, char const *argv[]) 7 | { 8 | int ProcessID; 9 | HANDLE hProcess; 10 | 11 | // 如果只有一个参数 12 | if(argc == 1) 13 | { 14 | help(); 15 | return 0; 16 | } 17 | 18 | // 如果有两个参数 19 | if(argc == 2) 20 | { 21 | // 获取进程id 22 | ProcessID = atoi(argv[1]); 23 | // 获取进程句柄 24 | hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, (DWORD)ProcessID ); 25 | // 终止进程 26 | TerminateProcess(hProcess, 0); 27 | } 28 | } 29 | 30 | void help() 31 | { 32 | printf("终止进程\n"); 33 | printf("kill <进程id>\n"); 34 | } -------------------------------------------------------------------------------- /10. threadTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DWORD WINAPI ThreadProc (LPVOID lpThreadParameter) 5 | { 6 | while(1) 7 | { 8 | printf("%s \n", (char *)lpThreadParameter); 9 | Sleep(533); 10 | } 11 | return 0; 12 | } 13 | 14 | int main() 15 | { 16 | DWORD Tid; 17 | char *PassData; 18 | 19 | PassData = "Hello 线程1"; 20 | 21 | CreateThread( 22 | NULL, // 不能被子进程继承 23 | 0, // 默认堆栈大小 24 | ThreadProc, // 线程调用函数过程 25 | PassData, // 传递参数 26 | 0, // 创建后立即执行 27 | &Tid // 保存创建后的线程ID 28 | ); 29 | 30 | printf("线程1 创建成功 线程ID:%u \n", Tid); 31 | 32 | PassData = "hi 线程2"; 33 | 34 | CreateThread( 35 | NULL, // 不能被子进程继承 36 | 0, // 默认堆栈大小 37 | ThreadProc, // 线程调用函数过程 38 | PassData, // 传递参数 39 | 0, // 创建后立即执行 40 | &Tid // 保存创建后的线程ID 41 | ); 42 | 43 | printf("线程2 创建成功 线程ID:%u \n", Tid); 44 | 45 | system("pause"); 46 | // 主线程暂停在这里等待用户按任意键,其他线程则继续执行 47 | // 不过一旦按下任意键,主线程退进程,则其他线程均终止 48 | // 注意这不是因为主线程的原因,在子线程中退进程效果一样 49 | // 因为线程是归属于进程的,进程退出那么旗下的所有线程也都会终止 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /11. snake.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // 后方函数申明 7 | void restart(); 8 | void gotoxy(int x,int y); 9 | 10 | // 方向对应值 11 | enum MoveDir { RIGHT = 0, UP = 1, LEFT = 2, DOWN = 3 }; 12 | 13 | // 开始时间戳, 结束时间戳 14 | time_t start,end; 15 | 16 | int food[25][20] = {0}; // 果实对应数组 17 | int snakel[25][20] = {0};// 蛇身对应数组 18 | 19 | int score = 0; // 得分 20 | int x = 0, y = 0; // 坐标 21 | int direct = RIGHT; // 移动方向 22 | int mark = 0; // 标记原方向 23 | 24 | int length = 0; // 蛇身链表长度 25 | int slength = 1; // 蛇身记录长度 26 | 27 | // 方向数组 28 | int dir[4][2]={ 29 | { 1, 0 }, // 0 向右 x坐标 +1 y坐标 +0 30 | { 0, -1 }, // 1 向上 x坐标 +0 y坐标 -1 31 | {-1, 0 }, // 2 向左 x坐标 -1 y坐标 +0 32 | { 0, 1 } // 3 向下 x坐标 +0 y坐标 +1 33 | }; 34 | 35 | /* 36 | snake 结构体 用于构建贪吃蛇链表 37 | */ 38 | struct snake 39 | { 40 | int x,y; 41 | struct snake *next,*pre; 42 | } *head, *tail, *p; // 声明结构体的同时定义头指针、尾指针、临时指针 43 | 44 | 45 | DWORD WINAPI ThreadProc(LPVOID lpPraram) 46 | { 47 | SYSTEMTIME sys; // 系统时间结构体 48 | 49 | // 线程启动时, 头尾指针均为空 50 | head = tail = NULL; 51 | int a , b; 52 | 53 | // 随即获取果实坐标 (a,b) 54 | a=(rand()+start)%25; // [0,24] 55 | b=(rand()+start)%20; // [0,19] 56 | 57 | /* Note 起始时间 start + 返回的随机值 rand() = 一个不规律的随机值 58 | * 随后 % 求模 25 即将这个书限制在0到25之内 */ 59 | 60 | // 子线程循环打印蛇身和果实 61 | while(1) 62 | { 63 | //打印已耗游戏时间; 64 | end = time(NULL);// 当前时间 65 | gotoxy(35,4); 66 | printf("%03d", (int)difftime(end,start)); // 当前时间与开始时间的差值 67 | 68 | GetLocalTime(&sys); // 获取当前时间 69 | 70 | //打印系统时间; 71 | gotoxy(28,18); 72 | printf("%4d/%02d/%02d", sys.wYear, sys.wMonth, sys.wDay ); 73 | gotoxy(29,19); 74 | printf("%02d:%02d:%02d", sys.wHour, sys.wMinute, sys.wSecond); 75 | 76 | //判断果实是否被吃了 77 | if(food[a][b] != '*' || snakel[a][b] == 1) 78 | { 79 | a=(rand()+start)%25; // [0,24] 80 | b=(rand()+start)%20; // [0,19] 81 | food[a][b]='*'; 82 | } 83 | 84 | // 到屏幕的(a,b)坐标打印果实 85 | gotoxy(a,b); printf("*"); 86 | 87 | //获取下一个坐标 88 | x += dir[direct][0]; 89 | y += dir[direct][1]; 90 | x += 25; x %= 25; 91 | y += 20; y %= 20; 92 | 93 | // 如果果实(food)数组中当前坐标对应为果实 94 | if(food[x][y]=='*') 95 | { 96 | slength++; // 蛇身长度自增 97 | score++; // 分数自增 98 | // 刷新分数 99 | gotoxy(35,3); printf("%03d",score); 100 | // 清理果实(food)数组 101 | food[x][y]=0; 102 | } 103 | // 若不是果实则,判断当前坐标是否为蛇身 104 | else if(snakel[x][y]==1) 105 | { 106 | // 如果是蛇身即玩家吃到自己,游戏重启 107 | restart(); 108 | } 109 | 110 | snakel[x][y]=1; // 蛇身对应新坐标置1 111 | 112 | // 创建新坐标对应的链表节点 113 | p = (snake*)malloc(sizeof(snake)); 114 | p->x = x; 115 | p->y = y; 116 | p->next = p->pre = NULL; 117 | 118 | if(head == NULL) { 119 | // 若只有一个节点(即蛇的长度为1,链表长度为0) 120 | head = tail = p; 121 | } 122 | else 123 | { 124 | // 若不只一个节点 125 | head->pre=p; // 头结点的前一个指向 p 节点 126 | p->next=head; // p 节点下一个指向当前头结点 127 | head=p; // 新的 p 变成头结点变成 128 | } 129 | 130 | length++; // 链表长度加1 131 | 132 | // 到新坐标,也就是头部打印 # 133 | gotoxy(head->x,head->y); 134 | printf("#"); 135 | 136 | // 输出调试信息 137 | gotoxy(49, 10); printf("length: %d slength: %d", length, slength); 138 | 139 | // 删除蛇尾 140 | if(length > slength) 141 | { 142 | // 清空蛇尾数组对应值 143 | snakel[tail->x][tail->y]=0; 144 | // 控制台输出流指针移动到蛇尾 145 | gotoxy(tail->x,tail->y); 146 | // 输出空格 147 | printf(" "); 148 | 149 | // 临时指针指向蛇尾 150 | p = tail; 151 | // 尾指针前移 152 | tail = tail->pre; 153 | // 释放原本的尾指针 154 | free(p); 155 | // 蛇身链表长度减1 156 | length--; 157 | } 158 | 159 | /* 160 | * 调控速度暂时休眠 161 | * 如果需要控制游戏速度只需要修改休眠的值即可 162 | */ 163 | _sleep(50); 164 | 165 | // 标记当前方向 166 | mark = direct; 167 | } 168 | } 169 | 170 | /* 171 | 初始化配置 172 | */ 173 | void init() 174 | { 175 | int i; 176 | 177 | // 绘制外围边框 178 | for( i=0; i<20; i++) 179 | { 180 | gotoxy(39,i); printf("|"); 181 | gotoxy(25,i); printf("|"); 182 | } 183 | for( i=0; i<40; i++) 184 | { 185 | gotoxy(i,20); printf("~"); 186 | } 187 | 188 | // 右侧游戏记录, 规则说明 189 | gotoxy(26, 3); printf("游戏得分:%03d",score); 190 | gotoxy(26, 4); printf("游戏时间:"); 191 | gotoxy(29,17); printf("系统时间"); 192 | 193 | gotoxy(49, 1); printf("@lellansin"); 194 | gotoxy(49, 2); printf("www.lellansin.com"); 195 | 196 | gotoxy(49, 4); printf("一群 10191598"); 197 | gotoxy(49, 5); printf("二群 163859361"); 198 | gotoxy(49, 6); printf("三群 10366953"); 199 | 200 | gotoxy(49, 8); printf("按ESC键退出"); 201 | 202 | // 初始化游戏开始时间 203 | start = time(NULL); 204 | } 205 | 206 | int main() 207 | { 208 | int i = 0; 209 | HANDLE sonThreadHandle; // 子线程句柄 210 | DWORD dwThreadId; // 子线程ID 211 | 212 | // 按键上半部分以及下半部分 213 | char keyCodePart1,keyCodePart2; 214 | 215 | // 执行初始化 216 | init(); 217 | 218 | //创建线程 219 | sonThreadHandle = CreateThread( 220 | NULL, // 不能被子进程继承 221 | 0, // 默认堆栈大小 222 | ThreadProc, // 线程调用函数过程 223 | NULL, // 传递参数 224 | 0, // 创建后立即执行 225 | &dwThreadId // 保存创建后的线程ID 226 | ); 227 | 228 | // 如果线程句柄为空,即新建线程失败 229 | if(sonThreadHandle == NULL) 230 | { 231 | ExitProcess(i); // 退进程, 程序结束 232 | } 233 | 234 | // 主线程循环获取按键 235 | while(1) 236 | { 237 | // getch 一次只能从输入流中读取一个字节 238 | // 不过一个按键通常是两个字节 239 | keyCodePart1 = getch(); // 获取第一个字节 240 | 241 | // 判断是否等于逃脱键(Esc)的第一个字节 242 | if(keyCodePart1 == 0x1b) 243 | { 244 | ExitProcess(2); // 是的话就退出进程 245 | } 246 | 247 | // 方向键第一个字节的值等于 -32 248 | if(keyCodePart1 == -32) 249 | { 250 | keyCodePart2 = getch(); // 获取第二个字节 251 | switch(keyCodePart2) 252 | { 253 | case(72): 254 | // direct=1; 255 | direct = UP; 256 | break; 257 | case(75): 258 | // direct=2; 259 | direct = LEFT; 260 | break; 261 | case(77): 262 | // direct=0; 263 | direct = RIGHT; 264 | break; 265 | case(80): 266 | // direct=3; 267 | direct = DOWN; 268 | break; 269 | } 270 | // 如果当前方向与原方向相反 271 | if( direct != mark && (direct+mark==RIGHT+LEFT||direct+mark==UP+DOWN) ) 272 | direct=mark; 273 | } 274 | /* 275 | 为什么是 0x1b 为什么是 -32 之类的值? 276 | 这些都是原本用同样的办法,两次 getch 之后 277 | 打印并记录下各个按键的值得到的判断 278 | */ 279 | } 280 | return 0; 281 | } 282 | 283 | void restart() 284 | { 285 | //判断死亡,重新开始游戏; 286 | MessageBox(NULL,(LPCSTR)"傻逼,死了吧!!!\Once More???",(LPCSTR)"GAME VOER!",MB_OK); 287 | 288 | // 分数清零 289 | score=0; gotoxy(35,3); printf("%03d",score); 290 | // 开始时间重记 291 | start = time(NULL); 292 | // 游戏已进行时间打印为0 293 | gotoxy(35,4); printf("%03d",0); 294 | 295 | // 从尾部开始循环消除蛇身 296 | while(tail) 297 | { 298 | // 休眠以延缓消除时间 299 | _sleep(200); 300 | snakel[tail->x][tail->y]=0; // 清除当前蛇身表的值 301 | // 移动到屏幕对应坐标输出宫格 302 | gotoxy(tail->x,tail->y); printf(" "); 303 | // 临时指针指向尾指针的前一个节点 304 | p = tail->pre; 305 | // 释放最后一个节点 306 | free(tail); 307 | // 临时节点变成新的尾部 308 | tail = p; 309 | } 310 | // 所有节点释放完毕,头尾指针清空 311 | head = tail = NULL; 312 | slength = 1; // 蛇身长度置1 313 | length=0; // 链表长度置0 314 | } 315 | 316 | 317 | /* 318 | 跳至控制台的(x,y)坐标 319 | */ 320 | void gotoxy(int x,int y) 321 | { 322 | COORD coord; // 控制台坐标结构体 323 | coord.X = x; 324 | coord.Y = y; 325 | SetConsoleCursorPosition( 326 | GetStdHandle( STD_OUTPUT_HANDLE ), // 获取控制台输出流的句柄 327 | coord // 设置输出位置的坐标 328 | ); 329 | } -------------------------------------------------------------------------------- /12. TestDLL/DLLTEST/dll.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lellansin/windows-api-tutorial/1f93da845a0c8524c6b2b9972443c506a5b4123c/12. TestDLL/DLLTEST/dll.h -------------------------------------------------------------------------------- /12. TestDLL/DLLTEST/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "dll.h" 4 | 5 | BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) 6 | { 7 | switch(dwReason) 8 | { 9 | // 动态链接库映射到某个进程的地址空间 10 | case DLL_PROCESS_ATTACH: 11 | /** 12 | * 当DLL刚被加载时触发(LoadLibrary),此处专门用来做初始化工作, 13 | * 如果初始化失败可以返回 false 这样DLL就不会被继续加载了 14 | **/ 15 | break; 16 | 17 | // 应用程序创建新的线程 18 | case DLL_THREAD_ATTACH: 19 | 20 | break; 21 | 22 | // 应用程序某个线程正常终止 23 | case DLL_THREAD_DETACH: 24 | 25 | break; 26 | 27 | // 动态链接库将被卸载 28 | case DLL_PROCESS_DETACH: 29 | /** 30 | * 当DLL将要被卸载时触发(FreeLibrary),此处专门用来做清理工作 31 | * 如关闭文件,释放内存空间等 32 | **/ 33 | break; 34 | } 35 | return 1; 36 | } 37 | 38 | void helloDLL(void) 39 | { 40 | MessageBox(NULL, TEXT("Hello DLL~"), TEXT("Title"), MB_OK); 41 | } -------------------------------------------------------------------------------- /12. TestDLL/LoadDLL/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | // 指向函数的指针类型 6 | typedef void (*fun_pointer)(void); 7 | 8 | // main 9 | VOID main(VOID) 10 | { 11 | HINSTANCE hDLL; 12 | BOOL flagGetFun = FALSE; 13 | fun_pointer p; 14 | 15 | // 加载 Dll 16 | hDLL = LoadLibrary(TEXT("DLLTEST.dll")); 17 | 18 | // 判断是否加载成功 19 | if (hDLL != NULL) 20 | { 21 | printf("模块加载成功\n"); 22 | 23 | // 获得指定导出函数的地址 24 | p = (fun_pointer) GetProcAddress(hDLL, "helloDLL"); 25 | 26 | // 判断是否成功 27 | if (NULL != p) 28 | { 29 | printf("函数获取成功,准备调用函数\n"); 30 | p(); // 成功则调用DLL中的函数 31 | }else 32 | { 33 | printf("函数获取失败!\n"); 34 | printf("error: %u\n", GetLastError()); 35 | } 36 | // 释放DLL 37 | if (!FreeLibrary(hDLL)) 38 | { 39 | printf("DLL释放失败\n"); 40 | printf("error: %u\n", GetLastError()); 41 | } 42 | }else 43 | { 44 | printf("模块加载失败!\n"); 45 | printf("error: %u\n", GetLastError()); 46 | } 47 | 48 | system("pause"); 49 | } -------------------------------------------------------------------------------- /13. CreateWindow.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | // 5. 窗口过程处理 5 | LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 6 | { 7 | switch(msg) 8 | { 9 | case WM_CLOSE: 10 | DestroyWindow(hwnd); 11 | break; 12 | case WM_DESTROY: 13 | PostQuitMessage(0); 14 | break; 15 | default: 16 | return DefWindowProc(hwnd, msg, wParam, lParam); 17 | } 18 | return 0; 19 | } 20 | 21 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 22 | LPSTR lpCmdLine, int nCmdShow) 23 | { 24 | WNDCLASSEX wc; // 更多详细都可以去百度的 http://baike.baidu.com/view/1750396.htm 25 | HWND hwnd; 26 | MSG Msg; 27 | char text[30]; 28 | 29 | const char szClassName[] = "myWindowClass"; 30 | 31 | // 1. 设置注册窗口结构体 32 | wc.cbSize = sizeof(WNDCLASSEX); // 注册窗口结构体的大小 33 | wc.style = 0; // 窗口的样式 34 | wc.lpfnWndProc = WndProc; // 指向窗口处理过程的函数指针 35 | wc.cbClsExtra = 0; // 指定紧跟在窗口类结构后的附加字节数 36 | wc.cbWndExtra = 0; // 指定紧跟在窗口事例后的附加字节数 37 | wc.hInstance = hInstance; // 本模块的实例句柄 38 | wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄 39 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标的句柄 40 | wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 背景画刷的句柄 41 | wc.lpszMenuName = NULL; // 指向菜单的指针 42 | wc.lpszClassName = szClassName; // 指向类名称的指针 43 | wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标 44 | 45 | // 2. 使用【窗口结构体】注册窗口 46 | if(!RegisterClassEx(&wc)) 47 | { 48 | MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK); 49 | return 0; 50 | } 51 | 52 | // 3. 创建窗口 53 | hwnd = CreateWindowEx( 54 | WS_EX_CLIENTEDGE, // 窗口的扩展风格 55 | szClassName, // 指向注册类名的指针 56 | TEXT("窗口标题"), // 指向窗口名称的指针 57 | WS_OVERLAPPEDWINDOW, // 窗口风格 58 | CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高 59 | NULL, // 父窗口的句柄 60 | NULL, // 菜单的句柄 61 | hInstance, // 应用程序实例的句柄 62 | NULL // 指向窗口的创建数据 63 | ); 64 | 65 | if(hwnd == NULL) 66 | { 67 | MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK); 68 | return 0; 69 | } 70 | 71 | // 4. 显示窗口 72 | ShowWindow(hwnd, nCmdShow); 73 | UpdateWindow(hwnd); 74 | 75 | // 6. 消息循环 76 | while(GetMessage(&Msg, NULL, 0, 0) > 0) 77 | { 78 | TranslateMessage(&Msg); 79 | DispatchMessage(&Msg); 80 | } 81 | return Msg.wParam; 82 | } -------------------------------------------------------------------------------- /14. KeyBoardHook.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | HWND hgWnd; 4 | HHOOK myhook; 5 | 6 | /**************************************************************** 7 | WH_KEYBOARD hook procedure 8 | 鍵盤钩子处理过程 9 | ****************************************************************/ 10 | LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 11 | { 12 | PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam; 13 | const char *info = NULL; 14 | char text[50], data[20]; 15 | 16 | PAINTSTRUCT ps; 17 | HDC hdc; 18 | 19 | if (nCode >= 0) 20 | { 21 | if (wParam == WM_KEYDOWN) info = "普通按鍵抬起"; 22 | else if (wParam == WM_KEYUP) info = "普通按鍵按下"; 23 | else if (wParam == WM_SYSKEYDOWN) info = "系統按鍵抬起"; 24 | else if (wParam == WM_SYSKEYUP) info = "系統按鍵按下"; 25 | 26 | ZeroMemory(text, sizeof(text)); 27 | ZeroMemory(data, sizeof(data)); 28 | wsprintf(text, "%s - 键盘码 [%04d], 扫描码 [%04d] ", info, p->vkCode, p->scanCode); 29 | wsprintf(data, "按鍵目測為: %c ", p->vkCode); 30 | 31 | hdc = GetDC(hgWnd); 32 | TextOut(hdc, 10, 10, text, strlen(text)); 33 | TextOut(hdc, 10, 30, data, strlen(data)); 34 | ReleaseDC(hgWnd,hdc); 35 | } 36 | 37 | return CallNextHookEx(myhook, nCode, wParam, lParam); 38 | } 39 | 40 | // 5. 窗口过程处理 41 | LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 42 | { 43 | hgWnd = hwnd; 44 | 45 | switch(msg) 46 | { 47 | case WM_CLOSE: 48 | DestroyWindow(hwnd); 49 | break; 50 | case WM_DESTROY: 51 | PostQuitMessage(0); 52 | break; 53 | default: 54 | return DefWindowProc(hwnd, msg, wParam, lParam); 55 | } 56 | return 0; 57 | } 58 | 59 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 60 | LPSTR lpCmdLine, int nCmdShow) 61 | { 62 | WNDCLASSEX wc; // http://baike.baidu.com/view/1750396.htm 63 | HWND hwnd; 64 | MSG Msg; 65 | char text[30]; 66 | 67 | const char szClassName[] = "myWindowClass"; 68 | 69 | // 1. 设置注册窗口结构体 70 | wc.cbSize = sizeof(WNDCLASSEX); // 注册窗口结构体的大小 71 | wc.style = 0; // 窗口的样式 72 | wc.lpfnWndProc = WndProc; // 指向窗口处理过程的函数指针 73 | wc.cbClsExtra = 0; // 指定紧跟在窗口类结构后的附加字节数 74 | wc.cbWndExtra = 0; // 指定紧跟在窗口事例后的附加字节数 75 | wc.hInstance = hInstance; // 本模块的实例句柄 76 | wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄 77 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标的句柄 78 | wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 背景画刷的句柄 79 | wc.lpszMenuName = NULL; // 指向菜单的指针 80 | wc.lpszClassName = szClassName; // 指向类名称的指针 81 | wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标 82 | 83 | // 2. 使用【窗口结构体】注册窗口 84 | if(!RegisterClassEx(&wc)) 85 | { 86 | MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK); 87 | return 0; 88 | } 89 | 90 | // 3. 创建窗口 91 | hwnd = CreateWindowEx( 92 | WS_EX_CLIENTEDGE, // 窗口的扩展风格 93 | szClassName, // 指向注册类名的指针 94 | TEXT("窗口标题"), // 指向窗口名称的指针 95 | WS_OVERLAPPEDWINDOW, // 窗口风格 96 | CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高 97 | NULL, // 父窗口的句柄 98 | NULL, // 菜单的句柄 99 | hInstance, // 应用程序实例的句柄 100 | NULL // 指向窗口的创建数据 101 | ); 102 | 103 | if(hwnd == NULL) 104 | { 105 | MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK); 106 | return 0; 107 | } 108 | 109 | // 4. 显示窗口 110 | ShowWindow(hwnd, nCmdShow); 111 | UpdateWindow(hwnd); 112 | 113 | // 设置键盘全局监听 114 | myhook = SetWindowsHookEx( 115 | WH_KEYBOARD_LL, // 监听类型【键盘】 116 | KeyboardProc, // 处理函数 117 | hInstance, // 当前实例句柄 118 | 0 // 监听窗口句柄(NULL为全局监听) 119 | ); 120 | 121 | if(myhook == NULL) 122 | { 123 | wsprintf(text, "键盘监听失败!error : %d \n", GetLastError()); 124 | MessageBox(hwnd, text, TEXT("错误"), MB_OK); 125 | } 126 | 127 | 128 | // 5. 消息循环 129 | while(GetMessage(&Msg, NULL, 0, 0) > 0) 130 | { 131 | TranslateMessage(&Msg); 132 | DispatchMessage(&Msg); 133 | } 134 | return Msg.wParam; 135 | } 136 | -------------------------------------------------------------------------------- /15. MouseHook.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | HWND hgWnd; 4 | HHOOK myhook; 5 | 6 | /**************************************************************** 7 | WH_KEYBOARD hook procedure 8 | 嫔毙钩子处理过程 9 | ****************************************************************/ 10 | LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) 11 | { 12 | LPMSLLHOOKSTRUCT p = (LPMSLLHOOKSTRUCT)lParam; 13 | POINT pt = p->pt; 14 | DWORD mouseData = p->mouseData; 15 | const char *info = NULL; 16 | char text[60], pData[50], mData[50]; 17 | 18 | PAINTSTRUCT ps; 19 | HDC hdc; 20 | 21 | if (nCode >= 0) 22 | { 23 | if (wParam == WM_MOUSEMOVE) info = "鼠标移动    "; 24 | else if(wParam == WM_LBUTTONDOWN) info = "鼠标【左键】按下"; 25 | else if(wParam == WM_LBUTTONUP) info = "鼠标【左键】抬起"; 26 | else if(wParam == WM_LBUTTONDBLCLK) info = "鼠标【左键】双击"; 27 | else if(wParam == WM_RBUTTONDOWN) info = "鼠标【右键】按下"; 28 | else if(wParam == WM_RBUTTONUP) info = "鼠标【右键】抬起"; 29 | else if(wParam == WM_RBUTTONDBLCLK) info = "鼠标【右键】双击"; 30 | else if(wParam == WM_MBUTTONDOWN) info = "鼠标【滚轮】按下"; 31 | else if(wParam == WM_MBUTTONUP) info = "鼠标【滚轮】抬起"; 32 | else if(wParam == WM_MBUTTONDBLCLK) info = "鼠标【滚轮】双击"; 33 | else if(wParam == WM_MOUSEWHEEL) info = "鼠标【滚轮】滚动"; 34 | 35 | ZeroMemory(text, sizeof(text)); 36 | ZeroMemory(pData, sizeof(pData)); 37 | ZeroMemory(mData, sizeof(mData)); 38 | 39 | wsprintf( text, "当前状态: %10s ", info); 40 | wsprintf(pData, "0x%x - X: [%04d], Y: [%04d] ", wParam, pt.x, pt.y); 41 | wsprintf(mData, "附带数据: %16u ", mouseData); 42 | 43 | hdc = GetDC(hgWnd); 44 | TextOut(hdc, 10, 10, text, strlen(text)); 45 | TextOut(hdc, 10, 30, pData, strlen(pData)); 46 | TextOut(hdc, 10, 50, mData, strlen(mData)); 47 | ReleaseDC(hgWnd,hdc); 48 | } 49 | 50 | return CallNextHookEx(myhook, nCode, wParam, lParam); 51 | } 52 | 53 | // 5. 窗口过程处理 54 | LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 55 | { 56 | hgWnd = hwnd; 57 | 58 | switch(msg) 59 | { 60 | case WM_CLOSE: 61 | DestroyWindow(hwnd); 62 | break; 63 | case WM_DESTROY: 64 | PostQuitMessage(0); 65 | break; 66 | default: 67 | return DefWindowProc(hwnd, msg, wParam, lParam); 68 | } 69 | return 0; 70 | } 71 | 72 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 73 | LPSTR lpCmdLine, int nCmdShow) 74 | { 75 | WNDCLASSEX wc; // http://baike.baidu.com/view/1750396.htm 76 | HWND hwnd; 77 | MSG Msg; 78 | char text[30]; 79 | 80 | const char szClassName[] = "myWindowClass"; 81 | 82 | // 1. 设置注册窗口结构体 83 | wc.cbSize = sizeof(WNDCLASSEX); // 注册窗口结构体的大小 84 | wc.style = 0; // 窗口的样式 85 | wc.lpfnWndProc = WndProc; // 指向窗口处理过程的函数指针 86 | wc.cbClsExtra = 0; // 指定紧跟在窗口类结构后的附加字节数 87 | wc.cbWndExtra = 0; // 指定紧跟在窗口事例后的附加字节数 88 | wc.hInstance = hInstance; // 本模块的实例句柄 89 | wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄 90 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标的句柄 91 | wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 背景画刷的句柄 92 | wc.lpszMenuName = NULL; // 指向菜单的指针 93 | wc.lpszClassName = szClassName; // 指向类名称的指针 94 | wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标 95 | 96 | // 2. 使用【窗口结构体】注册窗口 97 | if(!RegisterClassEx(&wc)) 98 | { 99 | MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK); 100 | return 0; 101 | } 102 | 103 | // 3. 创建窗口 104 | hwnd = CreateWindowEx( 105 | WS_EX_CLIENTEDGE, // 窗口的扩展风格 106 | szClassName, // 指向注册类名的指针 107 | TEXT("窗口标题"), // 指向窗口名称的指针 108 | WS_OVERLAPPEDWINDOW, // 窗口风格 109 | CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高 110 | NULL, // 父窗口的句柄 111 | NULL, // 菜单的句柄 112 | hInstance, // 应用程序实例的句柄 113 | NULL // 指向窗口的创建数据 114 | ); 115 | 116 | if(hwnd == NULL) 117 | { 118 | MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK); 119 | return 0; 120 | } 121 | 122 | // 4. 显示窗口 123 | ShowWindow(hwnd, nCmdShow); 124 | UpdateWindow(hwnd); 125 | 126 | // 设置键盘全局监听 127 | myhook = SetWindowsHookEx( 128 | WH_MOUSE_LL, // 监听类型【鼠标】 129 | MouseProc, // 处理函数 130 | hInstance, // 当前实例句柄 131 | 0 // 监听窗口句柄(NULL为全局监听) 132 | ); 133 | 134 | if(myhook == NULL) 135 | { 136 | wsprintf(text, "键盘监听失败!error : %d \n", GetLastError()); 137 | MessageBox(hwnd, text, TEXT("错误"), MB_OK); 138 | } 139 | 140 | 141 | // 5. 消息循环 142 | while(GetMessage(&Msg, NULL, 0, 0) > 0) 143 | { 144 | TranslateMessage(&Msg); 145 | DispatchMessage(&Msg); 146 | } 147 | return Msg.wParam; 148 | } 149 | 150 | -------------------------------------------------------------------------------- /16. hotkey_console.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | HWND act = GetActiveWindow(); 8 | 9 | if (RegisterHotKey( 10 | act, // 注册快捷键的窗口句柄 11 | 2, // 热键标识符避免热键冲突 12 | MOD_CONTROL | MOD_NOREPEAT, // Ctrl 键 No Repeat 不重复发送 13 | 'A' // A 14 | )) 15 | { 16 | printf("快捷键 Ctrl + A 注册成功! \n\n"); 17 | } 18 | 19 | MSG msg = {0}; 20 | // 循环获取操作系统发来的消息 21 | while (GetMessage(&msg, NULL, 0, 0) != 0) 22 | { 23 | // 当收到快捷键消息时 24 | if (msg.message == WM_HOTKEY) 25 | { 26 | printf("收到 WM_HOTKEY 快捷键消息\n"); 27 | CHAR text[50]; 28 | wsprintf(text, "wParam : 0x%x lParam : 0x%x \n", msg.wParam, msg.lParam); 29 | printf(text); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /17. hotkey_window.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void echo(LPSTR str) 4 | { 5 | MessageBox(NULL, str, TEXT("提示"), MB_OK); 6 | } 7 | 8 | // 5. 窗口过程处理 9 | LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 10 | { 11 | CHAR text[50]; 12 | switch(msg) 13 | { 14 | // 窗口创建消息 15 | case WM_CREATE: 16 | RegisterHotKey( 17 | hwnd, // 注册快捷键的窗口句柄 18 | 1, // 热键标识符避免热键冲突 19 | MOD_CONTROL | MOD_NOREPEAT, // Ctrl 键 No Repeat 不重复发送 20 | 'A' // A 21 | ); // Ctrl + A 22 | RegisterHotKey(hwnd, 2, MOD_CONTROL | MOD_NOREPEAT,'B');// Ctrl + B 23 | RegisterHotKey(hwnd, 3, MOD_ALT | MOD_NOREPEAT,'A'); // Alt + A 24 | RegisterHotKey(hwnd, 4, MOD_ALT | MOD_NOREPEAT,'B'); // Alt + B 25 | RegisterHotKey(hwnd, 5, MOD_NOREPEAT,'S'); // 直接按 S 26 | break; 27 | 28 | // 快捷键消息 29 | case WM_HOTKEY: 30 | /*** 31 | * wParam 保存注册时定义的热键标识符 32 | * lParam 高位存键(如A的值),低位存复合键的值(如Ctrl的值) 33 | */ 34 | //wsprintf(text, "wParam : %p lParam : %p", wParam, lParam); 35 | //echo(text); 36 | 37 | switch(LOWORD(lParam)) // 获取低16位的值 38 | { 39 | // 当用户先按 ctrl 40 | case MOD_CONTROL: 41 | 42 | switch(HIWORD(lParam)) // 获取高16位的值 43 | { 44 | case 'A': 45 | echo("Ctrl + A 被按下!"); 46 | break; 47 | case 'B': 48 | echo("Ctrl + B 被按下!"); 49 | break; 50 | } 51 | 52 | break; 53 | 54 | // 当用户先按 Alt 55 | case MOD_ALT: 56 | 57 | switch(HIWORD(lParam)) // 获取高16位的值 58 | { 59 | case 'A': 60 | echo("Alt + A 被按下!"); 61 | break; 62 | case 'B': 63 | echo("Alt + B 被按下!"); 64 | break; 65 | } 66 | 67 | break; 68 | 69 | // 没有组合键 70 | case 0: 71 | 72 | switch(HIWORD(lParam)) // 获取高16位的值 73 | { 74 | case 'S': 75 | echo("S 被按下"); 76 | break; 77 | } 78 | 79 | break; 80 | 81 | } 82 | break; 83 | 84 | case WM_CLOSE: 85 | DestroyWindow(hwnd); 86 | break; 87 | case WM_DESTROY: 88 | PostQuitMessage(0); 89 | break; 90 | default: 91 | return DefWindowProc(hwnd, msg, wParam, lParam); 92 | } 93 | return 0; 94 | } 95 | 96 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 97 | LPSTR lpCmdLine, int nCmdShow) 98 | { 99 | WNDCLASSEX wc; 100 | HWND hwnd; 101 | MSG Msg; 102 | char text[30]; 103 | 104 | const char szClassName[] = "myWindowClass"; 105 | 106 | // 1. 设置注册窗口结构体 107 | wc.cbSize = sizeof(WNDCLASSEX); // 注册窗口结构体的大小 108 | wc.style = 0; // 窗口的样式 109 | wc.lpfnWndProc = WndProc; // 指向窗口处理过程的函数指针 110 | wc.cbClsExtra = 0; // 指定紧跟在窗口类结构后的附加字节数 111 | wc.cbWndExtra = 0; // 指定紧跟在窗口事例后的附加字节数 112 | wc.hInstance = hInstance; // 本模块的实例句柄 113 | wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION); // 图标的句柄 114 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 光标的句柄 115 | wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 背景画刷的句柄 116 | wc.lpszMenuName = NULL; // 指向菜单的指针 117 | wc.lpszClassName = szClassName; // 指向类名称的指针 118 | wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION); // 和窗口类关联的小图标 119 | 120 | // 2. 使用【窗口结构体】注册窗口 121 | if(!RegisterClassEx(&wc)) 122 | { 123 | MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK); 124 | return 0; 125 | } 126 | 127 | // 3. 创建窗口 128 | hwnd = CreateWindowEx( 129 | WS_EX_CLIENTEDGE, // 窗口的扩展风格 130 | szClassName, // 指向注册类名的指针 131 | TEXT("窗口标题"), // 指向窗口名称的指针 132 | WS_OVERLAPPEDWINDOW, // 窗口风格 133 | CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高 134 | NULL, // 父窗口的句柄 135 | NULL, // 菜单的句柄 136 | hInstance, // 应用程序实例的句柄 137 | NULL // 指向窗口的创建数据 138 | ); 139 | 140 | if(hwnd == NULL) 141 | { 142 | MessageBox(NULL, TEXT("窗口创建失败"), TEXT("错误"),MB_ICONEXCLAMATION | MB_OK); 143 | return 0; 144 | } 145 | 146 | // 4. 显示窗口 147 | ShowWindow(hwnd, nCmdShow); 148 | UpdateWindow(hwnd); 149 | 150 | // 6. 消息循环 151 | while(GetMessage(&Msg, NULL, 0, 0) > 0) 152 | { 153 | TranslateMessage(&Msg); 154 | DispatchMessage(&Msg); 155 | } 156 | return Msg.wParam; 157 | } -------------------------------------------------------------------------------- /18. hotkey_complex.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | MSG msg = {0}; 8 | HWND hConsole = GetActiveWindow(); 9 | 10 | // Ctrl + D 11 | RegisterHotKey(hConsole,2,MOD_CONTROL | MOD_NOREPEAT,'D'); 12 | // Win键 + Z 13 | RegisterHotKey(hConsole,2,MOD_WIN | MOD_NOREPEAT,'Z'); 14 | // Ctrl + Alt + S 15 | RegisterHotKey(hConsole,2,MOD_CONTROL | MOD_ALT | MOD_NOREPEAT,'S'); 16 | // Ctrl + Alt + Shift + A 17 | RegisterHotKey(hConsole,2,MOD_CONTROL | MOD_ALT | MOD_SHIFT | MOD_NOREPEAT,'A'); 18 | 19 | // 循环获取操作系统发来的消息 20 | while (GetMessage(&msg, NULL, 0, 0) != 0) 21 | { 22 | // 当收到快捷键消息时 23 | if (msg.message == WM_HOTKEY) 24 | { 25 | printf("收到 WM_HOTKEY 快捷键消息\n"); 26 | printf("wParam : 0x%x lParam : 0x%x \n", msg.wParam, msg.lParam); 27 | 28 | switch(LOWORD(msg.lParam)) // 获取低16位的值 29 | { 30 | // 当用户先按 Ctrl 31 | case MOD_CONTROL: 32 | switch(HIWORD(msg.lParam)) 33 | { 34 | case 'D': 35 | printf("Ctrl + D 被按下! \n\n"); 36 | break; 37 | } 38 | break; 39 | 40 | // 当用户先按 Windows 键 41 | case MOD_WIN: 42 | switch(HIWORD(msg.lParam)) 43 | { 44 | case 'Z': 45 | printf("Win + Z 被按下! \n\n"); 46 | break; 47 | } 48 | break; 49 | 50 | // 当用户先按 Ctrl + Alt 51 | case MOD_CONTROL | MOD_ALT: 52 | switch(HIWORD(msg.lParam)) // 获取高16位的值 53 | { 54 | case 'S': 55 | printf("Ctrl + Alt + S 被按下! \n\n"); 56 | break; 57 | } 58 | break; 59 | 60 | // 当用户先按 Ctrl + Alt + Shift 61 | case MOD_CONTROL | MOD_ALT | MOD_SHIFT: 62 | switch(HIWORD(msg.lParam)) // 获取高16位的值 63 | { 64 | case 'A': 65 | printf("Ctrl + Alt + Shift + A 被按下! \n\n"); 66 | break; 67 | } 68 | break; 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TCP_SCOKET_CLIENT_TEST", "TCP_SCOKET_CLIENT_TEST\TCP_SCOKET_CLIENT_TEST.vcxproj", "{77471033-D378-4138-B1D9-B1AB918CB90B}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {77471033-D378-4138-B1D9-B1AB918CB90B}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {77471033-D378-4138-B1D9-B1AB918CB90B}.Debug|Win32.Build.0 = Debug|Win32 14 | {77471033-D378-4138-B1D9-B1AB918CB90B}.Release|Win32.ActiveCfg = Release|Win32 15 | {77471033-D378-4138-B1D9-B1AB918CB90B}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lellansin/windows-api-tutorial/1f93da845a0c8524c6b2b9972443c506a5b4123c/19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST.suo -------------------------------------------------------------------------------- /19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {77471033-D378-4138-B1D9-B1AB918CB90B} 15 | TCP_SCOKET_CLIENT_TEST 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Level3 43 | Disabled 44 | 45 | 46 | true 47 | 48 | 49 | 50 | 51 | Level3 52 | MaxSpeed 53 | true 54 | true 55 | 56 | 57 | true 58 | true 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SCOKET_CLIENT_TEST/TCP_SCOKET_CLIENT_TEST/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma comment(lib, "ws2_32.lib") 4 | 5 | void main() 6 | { 7 | int err; 8 | char *message; 9 | char recvBuf[100]; 10 | 11 | SOCKET sockClient; // 客户端 Scoket 12 | SOCKADDR_IN addrServer; // 服务端地址 13 | 14 | WSADATA wsaData; 15 | WORD wVersionRequested; 16 | 17 | wVersionRequested = MAKEWORD( 2, 2 ); 18 | 19 | err = WSAStartup( wVersionRequested, &wsaData ); 20 | 21 | if ( err != 0 ) 22 | { 23 | return; 24 | } 25 | 26 | if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) 27 | { 28 | // 启动错误,程序结束 29 | WSACleanup( ); 30 | return; 31 | } 32 | 33 | // 新建客户端 scoket 34 | sockClient = socket(AF_INET, SOCK_STREAM, 0); 35 | 36 | // 定义要连接的服务端地址 37 | addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 目标IP (127.0.0.1是本机地址) 38 | addrServer.sin_family = AF_INET; // 协议类型是INET 39 | addrServer.sin_port = htons(6000); // 连接端口1234 40 | 41 | // 让 sockClient 连接到 服务端 42 | connect(sockClient, (SOCKADDR *)&addrServer, sizeof(SOCKADDR)); 43 | 44 | // 从服务端获取数据 45 | recv(sockClient, recvBuf, 100, 0); 46 | 47 | // 打印数据 48 | printf("%s\n", recvBuf); 49 | 50 | message = "服务端你好~"; 51 | 52 | // 发送数据到服务端 53 | send(sockClient, message, strlen(message) + 1, 0); 54 | 55 | // 关闭socket 56 | closesocket(sockClient); 57 | WSACleanup(); 58 | 59 | getchar(); // 暂停 60 | } 61 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TCP_SOCKET_SERVER_TEST", "TCP_SOCKET_SERVER_TEST\TCP_SOCKET_SERVER_TEST.vcxproj", "{6335849E-09F0-4279-A65A-EABD8C13E188}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {6335849E-09F0-4279-A65A-EABD8C13E188}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {6335849E-09F0-4279-A65A-EABD8C13E188}.Debug|Win32.Build.0 = Debug|Win32 14 | {6335849E-09F0-4279-A65A-EABD8C13E188}.Release|Win32.ActiveCfg = Release|Win32 15 | {6335849E-09F0-4279-A65A-EABD8C13E188}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lellansin/windows-api-tutorial/1f93da845a0c8524c6b2b9972443c506a5b4123c/19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST.suo -------------------------------------------------------------------------------- /19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {6335849E-09F0-4279-A65A-EABD8C13E188} 15 | TCP_SOCKET_SERVER_TEST 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Level3 43 | Disabled 44 | 45 | 46 | true 47 | 48 | 49 | 50 | 51 | Level3 52 | MaxSpeed 53 | true 54 | true 55 | 56 | 57 | true 58 | true 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_SOCKET_SERVER_TEST/TCP_SOCKET_SERVER_TEST/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma comment(lib, "ws2_32.lib") 4 | 5 | void main() 6 | { 7 | int err; // 错误信息 8 | int len; 9 | 10 | char sendBuf[100]; // 发送至客户端的字符串 11 | char recvBuf[100]; // 接受客户端返回的字符串 12 | 13 | SOCKET sockServer; // 服务端 Socket 14 | SOCKADDR_IN addrServer;// 服务端地址 15 | SOCKET sockClient; // 客户端 Scoket 16 | SOCKADDR_IN addrClient;// 客户端地址 17 | 18 | WSADATA wsaData; // winsock 结构体 19 | WORD wVersionRequested;// winsock 的版本 20 | 21 | // 配置 Windows Socket版本 22 | wVersionRequested = MAKEWORD( 2, 2 ); 23 | 24 | // 初始化 Windows Socket 25 | err = WSAStartup( wVersionRequested, &wsaData ); 26 | 27 | if ( err != 0 ) 28 | { 29 | // 启动错误,程序结束 30 | return; 31 | } 32 | 33 | /* 34 | * 确认WinSock DLL支持2.2 35 | * 请注意如果DLL支持的版本大于2.2至2.2 36 | * 它仍然会返回wVersion2.2的版本 37 | */ 38 | 39 | if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) 40 | { 41 | // 启动错误,程序结束 42 | WSACleanup(); // 终止Winsock 2 DLL (Ws2_32.dll) 的使用 43 | return; 44 | } 45 | 46 | // 定义服务器端socket 47 | sockServer = socket(AF_INET, SOCK_STREAM, 0); 48 | 49 | // 设置服务端 socket 50 | addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本机IP 51 | addrServer.sin_family = AF_INET; // 协议类型是INET 52 | addrServer.sin_port = htons(6000); // 绑定端口6000 53 | 54 | // 将服务器端socket绑定在本地端口 55 | bind(sockServer, (SOCKADDR *)&addrServer, sizeof(SOCKADDR)); 56 | 57 | // Listen 监听端口 58 | listen(sockServer, 5); // 5 为等待连接数目 59 | 60 | printf("服务器已启动:\n监听中...\n"); 61 | 62 | len = sizeof(SOCKADDR); 63 | 64 | while (1) 65 | { 66 | // accept 会阻塞进程,直到有客户端连接上来为止 67 | sockClient = accept(sockServer, (SOCKADDR *)&addrClient, &len); 68 | // 当客户端连接上来时, 拼接如下字符串 69 | sprintf(sendBuf, "欢迎 ip: %s 的用户连接, 这里是 Lellansin 的服务器\n", inet_ntoa(addrClient.sin_addr)); 70 | // 向客户端发送字符串 71 | send(sockClient, sendBuf, strlen(sendBuf) + 1, 0); 72 | // 获取客户端返回的数据 73 | recv(sockClient, recvBuf, 100, 0); 74 | // 打印客户端返回的数据 75 | printf("%s\n", recvBuf); 76 | // 关闭socket 77 | closesocket(sockClient); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /19. Scoket example/TCP_Scoket_Client.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lellansin/windows-api-tutorial/1f93da845a0c8524c6b2b9972443c506a5b4123c/19. Scoket example/TCP_Scoket_Client.zip -------------------------------------------------------------------------------- /19. Scoket example/TCP_Socket_Server.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lellansin/windows-api-tutorial/1f93da845a0c8524c6b2b9972443c506a5b4123c/19. Scoket example/TCP_Socket_Server.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Lellansin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 本系列文章,旨在为有一定C语言基础而想进一步学习一些 windows 上编程的人规划一条道路。也即本教程的内容不一定详实,性质类似于入门路标指南。 2 | 至于能不能达到比较好的水平,博主在继续努力,也希望各位朋友反馈来帮助博主提高文章的质量与水平。 3 | 4 |

Windows API 教程

5 | 6 | 21 | 22 | PS: 本教程源代码原本放在百度网盘,但是由于网盘多次整改,近期在往 github 迁移。 23 | -------------------------------------------------------------------------------- /port/port.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "port", "port\port.vcxproj", "{90647D94-0D00-4121-97DE-F8AD6AB6044D}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {90647D94-0D00-4121-97DE-F8AD6AB6044D}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {90647D94-0D00-4121-97DE-F8AD6AB6044D}.Debug|Win32.Build.0 = Debug|Win32 14 | {90647D94-0D00-4121-97DE-F8AD6AB6044D}.Release|Win32.ActiveCfg = Release|Win32 15 | {90647D94-0D00-4121-97DE-F8AD6AB6044D}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /port/port.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lellansin/windows-api-tutorial/1f93da845a0c8524c6b2b9972443c506a5b4123c/port/port.suo -------------------------------------------------------------------------------- /port/port/port.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #pragma comment(lib,"ws2_32.lib") 5 | 6 | void Help( void ); 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | WORD wVersion = MAKEWORD(2, 0); 11 | WSADATA wsaData; 12 | 13 | //sockaddr_in结构体 14 | struct sockaddr_in sin; 15 | 16 | int iFromPort; 17 | int iToPort; 18 | int iNowPort; 19 | char *cHost; 20 | 21 | HOSTENT *host_entry; 22 | char *host_name; 23 | char host_address[256]; 24 | 25 | SOCKET s; 26 | 27 | int iOpenPort = 0; 28 | int port[256], i; 29 | 30 | if (argc != 4) 31 | { 32 | Help(); 33 | return -1; 34 | } 35 | 36 | iFromPort = atoi(argv[2]); 37 | iToPort = atoi(argv[3]); 38 | host_name = argv[1]; 39 | 40 | if (iFromPort > iToPort || iFromPort < 0 || iFromPort > 65535 || iToPort < 0 || iToPort > 65535) 41 | { 42 | printf("起始端口不能大于结束端口,且范围为:1--65535 "); 43 | return 0; 44 | } 45 | 46 | if ( WSAStartup(wVersion , &wsaData) ) 47 | { 48 | printf("初始化失败!"); 49 | return -1; 50 | } 51 | 52 | host_entry = gethostbyname(host_name); 53 | 54 | if (host_entry != 0) 55 | { 56 | wsprintf( host_address, "%d.%d.%d.%d", 57 | (host_entry->h_addr_list[0][0] & 0x00ff), 58 | (host_entry->h_addr_list[0][1] & 0x00ff), 59 | (host_entry->h_addr_list[0][2] & 0x00ff), 60 | (host_entry->h_addr_list[0][3] & 0x00ff) 61 | ); 62 | printf("\n主机名称:%s 主机地址:%s \n", host_name, host_address); 63 | } 64 | 65 | cHost = host_address; 66 | 67 | printf("======= 开始扫描 ======= \n"); 68 | 69 | for (iNowPort = iFromPort; iNowPort <= iToPort; iNowPort++) 70 | { 71 | s = socket(AF_INET, SOCK_STREAM, 0); 72 | if (s == INVALID_SOCKET) 73 | { 74 | printf("create socket() failed!"); 75 | WSACleanup(); 76 | } 77 | 78 | sin.sin_family = AF_INET; 79 | sin.sin_port = htons(iNowPort); 80 | sin.sin_addr.S_un.S_addr = inet_addr(cHost); 81 | 82 | if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR) 83 | { 84 | printf("%s -> %d:未开放 \n", cHost, iNowPort); 85 | closesocket(s); 86 | } 87 | else 88 | { 89 | printf("%s -> %d:开放 \n", cHost, iNowPort); 90 | port[iOpenPort] = iNowPort; 91 | iOpenPort ++; 92 | closesocket(s); 93 | } 94 | } 95 | 96 | printf("======= 扫描结果 ======= \n"); 97 | printf("主机:%s 扫描到%d个端口,分别是: \n", host_name, iOpenPort); 98 | 99 | for ( i = 0; i < iOpenPort; i++) 100 | { 101 | printf("%d ", port[i]); 102 | } 103 | 104 | //关闭socket 105 | closesocket(s); 106 | WSACleanup(); 107 | return 0; 108 | } 109 | 110 | //帮助函数 111 | void Help() 112 | { 113 | printf("Usage: \n"); 114 | printf("Port.exe \n"); 115 | printf("Example: \n"); 116 | printf("Port.exe 127.0.0.1 100 200 "); 117 | } -------------------------------------------------------------------------------- /port/port/port.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {90647D94-0D00-4121-97DE-F8AD6AB6044D} 15 | port 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Level3 43 | Disabled 44 | 45 | 46 | true 47 | 48 | 49 | 50 | 51 | Level3 52 | MaxSpeed 53 | true 54 | true 55 | 56 | 57 | true 58 | true 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /port/port/port.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /port/port/port.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | --------------------------------------------------------------------------------