分类: Other
解决 zliab1.dll 错误的办法
zlib 是一款开源的数据压缩库。很多软件都选用了这款软件来实现自己的功能。开源软件的很大特点就是版本众多,如果你遇到了如下图所示的错误
“The ordinal 55 could not be located in the dynamic link library zlib1.dll”(英文环境)
或者“无法定位序数 55 于动态链接库 zlib1.dll 上”(中文环境)
那么你需要找一个正确的 zlib1.dll 版本放在你运行的程序目录下。此外,还可能遇到 “无法定位序数 73 于动态链接库 zlib1.dll 上” 等等
下载这个 zlib1.dll 包,里面有各种版本,一个个实验总有一款适合你。(“无法定位序数 73”的问题可以使用 1.2.3.2027 版解决)
VirtualBox WinXP 蓝屏问题
在 VirtualBox 中安装了一个 Windows XP,结果遇到每次进入桌面就重启动的问题。能够进入“安全模式”。于是用 WinDBG 分析Dump File,结果如下
是 “IntelPPM.sys” 导致的。
在网上搜索 VirtualBox IntelPPM.sys 发现很多人遇到这样的问题。有人建议直接删除这个SYS文件,我试验过并不好用,最后是从安全模式进入,启动注册表
在下面的键值中,将 Start 修改为 4
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Intelppm
再次重启就OK了。
参考:
1.“Problems with Intelppm.sys and processr.sys under Virtual PC / Virtual Server”
http://blogs.msdn.com/b/virtual_pc_guy/archive/2005/10/24/484461.aspx
又一种枚举当前系统中硬盘的方法(2)
这次使用 SetupDiGetClassDevs 和 SetupDiEnumDeviceInterfaces 函数直接查询系统中的硬盘信息。具体的解释,请参考
http://cutebunny.blog.51cto.com/301216/625577 《windows的磁盘操作之七——获取当前所有的物理磁盘号》 这是非常好的文章。
枚举的结果并非 \\.\PhysicalDriveX 而是类似 \\?\usbstor#disk&ven_adata&prod_usb_flash_drive&rev_1.00#000000000000000922&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 这样的字符串。(天杀同学指出:这种符号连接,是链接到atapi生成的设备,比如\device\ide\idedeviceP0TTolo-3这种设备上的,这个设备上面会附加\Device\Harddisk0\DR0,应用程序打开\\?\ide#xxxx这个,就和打开\\.\PhysicalDrive0一样了,因为请求在驱动里面都是从上层往下层传递的. )同样可以直接给CreateFile作为参数使用。
另外,这个程序如果直接运行,会出现打印出来上述字符串,然后又显示 “CreateFile() Error: 5”的问题。这个错误表示 “Access denied”.
它是由于在程序中使用CreateFile而没有相应的权限导致的。
程序中使用了很多C语言的变长数组,这在我看起来无比诡异…….
编译中需要加入 lib,具体方式请参考下图
运行结果如下图,可以看到,最后还给出了硬盘号。
这样的方法更精确一些,在很多硬盘的情况下会节省查询的时间,但是和1中的方法相比,复杂度提高了很多倍。
代码如下
// phylist1.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <stdio.h> #include <conio.h> #include <winioctl.h> #include <setupapi.h> #define MAX_DEVICE 10 #define INTERFACE_DETAIL_SIZE (1024) DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); /****************************************************************************** * Function: get device path from GUID * input: lpGuid, GUID pointer * output: pszDevicePath, device paths * return: Succeed, the amount of found device paths * Fail, -1 ******************************************************************************/ DWORD GetDevicePath(LPGUID lpGuid, WCHAR **pszDevicePath) { HDEVINFO hDevInfoSet; SP_DEVICE_INTERFACE_DATA ifdata; PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail; DWORD nCount; BOOL result; //get a handle to a device information set hDevInfoSet = SetupDiGetClassDevs( lpGuid, // class GUID NULL, // Enumerator NULL, // hwndParent DIGCF_PRESENT | DIGCF_DEVICEINTERFACE // present devices ); //fail... if (hDevInfoSet == INVALID_HANDLE_VALUE) { fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError()); return (DWORD)-1; } pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(INTERFACE_DETAIL_SIZE); if (pDetail == NULL) { return (DWORD)-1; } pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); nCount = 0; result = TRUE; // device index = 0, 1, 2... test the device interface one by one while (result) { ifdata.cbSize = sizeof(ifdata); //enumerates the device interfaces that are contained in a device information set result = SetupDiEnumDeviceInterfaces( hDevInfoSet, // DeviceInfoSet NULL, // DeviceInfoData lpGuid, // GUID nCount, // MemberIndex &ifdata // DeviceInterfaceData ); if (result) { // get details about a device interface result = SetupDiGetDeviceInterfaceDetail( hDevInfoSet, // DeviceInfoSet &ifdata, // DeviceInterfaceData pDetail, // DeviceInterfaceDetailData INTERFACE_DETAIL_SIZE, // DeviceInterfaceDetailDataSize NULL, // RequiredSize NULL // DeviceInfoData ); if (result) { // copy the path to output buffer wcscpy(pszDevicePath[nCount], pDetail->DevicePath); printf("%ws\n", pDetail->DevicePath); nCount++; } } } free(pDetail); (void)SetupDiDestroyDeviceInfoList(hDevInfoSet); return nCount; } /****************************************************************************** * Function: get all present disks' physical number * input: N/A * output: ppDisks, array of disks' physical number * return: Succeed, the amount of present disks * Fail, -1 ******************************************************************************/ DWORD GetAllPresentDisks(DWORD **ppDisks) { WCHAR *szDevicePath[MAX_DEVICE]; // device path DWORD nDevice; HANDLE hDevice; STORAGE_DEVICE_NUMBER number; BOOL result; DWORD readed; WORD i, j; for (i = 0; i < MAX_DEVICE; i++) { szDevicePath[i] = (WCHAR *)malloc(INTERFACE_DETAIL_SIZE); if (NULL == szDevicePath[i]) { for (j = 0; j < i; j++) { free(szDevicePath[i]); } return (DWORD)-1; } } // get the device paths nDevice = GetDevicePath(const_cast<LPGUID>(&GUID_DEVINTERFACE_DISK), szDevicePath); if ((DWORD)-1 == nDevice) { for (i = 0; i < MAX_DEVICE; i++) { free(szDevicePath[i]); } return (DWORD)-1; } *ppDisks = (DWORD *)malloc(sizeof(DWORD) * nDevice); // get the disk's physical number one by one for (i = 0; i < nDevice; i++) { hDevice = CreateFile( szDevicePath[i], // drive to open GENERIC_READ | GENERIC_WRITE, // access to the drive FILE_SHARE_READ | FILE_SHARE_WRITE, //share mode NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL // do not copy file attribute ); if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive { for (j = 0; j < MAX_DEVICE; j++) { free(szDevicePath[j]); } free(*ppDisks); fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError()); return DWORD(-1); } result = DeviceIoControl( hDevice, // handle to device IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode NULL, // lpInBuffer 0, // nInBufferSize &number, // output buffer sizeof(number), // size of output buffer &readed, // number of bytes returned NULL // OVERLAPPED structure ); if (!result) // fail { fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError()); for (j = 0; j < MAX_DEVICE; j++) { free(szDevicePath[j]); } free(*ppDisks); (void)CloseHandle(hDevice); return (DWORD)-1; } *(*ppDisks + i) = number.DeviceNumber; // printf("%d\n",number.DeviceNumber); (void)CloseHandle(hDevice); } for (i = 0; i < MAX_DEVICE; i++) { free(szDevicePath[i]); } return nDevice; } int _tmain(int argc, _TCHAR* argv[]) { DWORD *pDisk; int t,j; t=GetAllPresentDisks(&pDisk); for (j=0; j<t;j++) { printf("%d \n", *pDisk++); } _getch(); return 0; }
完整代码下载
枚举当前系统中硬盘的方法(1)
枚举的结果是 “\\.\PhysicalDriveX”这样的形式。
需要注意的是:程序必须在 Administrator 权限下运行。即运行时,要求 “Run as Administrator”。同样在VS2008中编译时,由于权限不够,可能无法看到运行结果。本程序使用的是最传统的方法,使用CreateFile尝试不同的 PhysicalDirve+Number如果能够打开就是存在的。
#include "stdafx.h" #include <windows.h> #include <stdio.h> #include <conio.h> int _tmain(int argc, _TCHAR* argv[]) { int i; TCHAR Device[0x20]; HANDLE hDevice; for (i=0;i<10;i++) { wsprintf(Device,TEXT("\\\\.\\PhysicalDrive%d"), i); hDevice = CreateFile(Device, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL); if (hDevice!=INVALID_HANDLE_VALUE) {printf("%ws \n",Device); } CloseHandle( hDevice ); } _getch(); return 0; }
获得当前系统增加/移除USB设备名称的方法 VC (2)
上面一篇文章给出了 Delphi 版本获得当前系统增加/移除USB设备名称的方法。这篇给出一个VC 的版本。编译器为 VS2008 Express,代码如下
#include "stdafx.h" #include <windows.h> #include <stdio.h> #include <tchar.h> #include <strsafe.h> #include <dbt.h> #include <Shellapi.h> // This GUID is for all USB /* A5DCBF10-6530-11D2-901F-00C04FB951ED */ GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED }; // For informational messages and window titles PWSTR g_pszAppName; // Forward declarations void OutputMessage(HWND hOutWnd, WPARAM wParam, LPARAM lParam); void ErrorHandler(LPTSTR lpszFunction); // // DoRegisterDeviceInterfaceToHwnd // BOOL DoRegisterDeviceInterfaceToHwnd( IN GUID InterfaceClassGuid, IN HWND hWnd, OUT HDEVNOTIFY *hDeviceNotify ) // Routine Description: // Registers an HWND for notification of changes in the device interfaces // for the specified interface class GUID. // Parameters: // InterfaceClassGuid - The interface class GUID for the device // interfaces. // hWnd - Window handle to receive notifications. // hDeviceNotify - Receives the device notification handle. On failure, // this value is NULL. // Return Value: // If the function succeeds, the return value is TRUE. // If the function fails, the return value is FALSE. // Note: // RegisterDeviceNotification also allows a service handle be used, // so a similar wrapper function to this one supporting that scenario // could be made from this template. { DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = InterfaceClassGuid; *hDeviceNotify = RegisterDeviceNotification( hWnd, // events recipient &NotificationFilter, // type of device DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle ); if ( NULL == *hDeviceNotify ) { ErrorHandler(TEXT("RegisterDeviceNotification")); return FALSE; } return TRUE; } // // MessagePump // void MessagePump( HWND hWnd ) // Routine Description: // Simple main thread message pump. // // Parameters: // hWnd - handle to the window whose messages are being dispatched // Return Value: // None. { MSG msg; int retVal; // Get all messages for any window that belongs to this thread, // without any filtering. Potential optimization could be // obtained via use of filter values if desired. while( (retVal = GetMessage(&msg, NULL, 0, 0)) != 0 ) { if ( retVal == -1 ) { ErrorHandler(TEXT("GetMessage")); break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } } // // WinProcCallback // INT_PTR WINAPI WinProcCallback( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) // Routine Description: // Simple Windows callback for handling messages. // This is where all the work is done because the example // is using a window to process messages. This logic would be handled // differently if registering a service instead of a window. // Parameters: // hWnd - the window handle being registered for events. // message - the message being interpreted. // wParam and lParam - extended information provided to this // callback by the message sender. // For more information regarding these parameters and return value, // see the documentation for WNDCLASSEX and CreateWindowEx. { LRESULT lRet = 1; static HDEVNOTIFY hDeviceNotify; static HWND hEditWnd; static ULONGLONG msgCount = 0; switch (message) { case WM_CREATE: // // This is the actual registration., In this example, registration // should happen only once, at application startup when the window // is created. // // If you were using a service, you would put this in your main code // path as part of your service initialization. // if ( ! DoRegisterDeviceInterfaceToHwnd( GUID_DEVINTERFACE_USB_DEVICE, hWnd, &hDeviceNotify) ) { // Terminate on failure. ErrorHandler(TEXT("DoRegisterDeviceInterfaceToHwnd")); ExitProcess(1); } // // Make the child window for output. // hEditWnd = CreateWindow(TEXT("EDIT"),// predefined class NULL, // no window title WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL, 0, 0, 0, 0, // set size in WM_SIZE message hWnd, // parent window (HMENU)1, // edit control ID (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE), NULL); // pointer not needed if ( hEditWnd == NULL ) { // Terminate on failure. ErrorHandler(TEXT("CreateWindow: Edit Control")); ExitProcess(1); } // Add text to the window. SendMessage(hEditWnd, WM_SETTEXT, 0, (LPARAM)TEXT("Registered for USB device notification...\n")); break; case WM_SETFOCUS: SetFocus(hEditWnd); break; case WM_SIZE: // Make the edit control the size of the window's client area. MoveWindow(hEditWnd, 0, 0, // starting x- and y-coordinates LOWORD(lParam), // width of client area HIWORD(lParam), // height of client area TRUE); // repaint window break; case WM_DEVICECHANGE : { // // This is the actual message from the interface via Windows messaging. // This code includes some additional decoding for this particular device type // and some common validation checks. // // Note that not all devices utilize these optional parameters in the same // way. Refer to the extended information for your particular device type // specified by your GUID. // PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam; TCHAR strBuff[256]; // Output some messages to the window. switch (wParam) { case DBT_DEVICEARRIVAL: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: DBT_DEVICEARRIVAL\n"), msgCount); OutputMessage(hEditWnd, wParam, (LPARAM)strBuff); StringCchPrintf( strBuff, 256, TEXT("USB Device information: \n")); OutputMessage(hEditWnd, wParam, (LPARAM)strBuff); //MultiByteToWideChar(CP_ACP, 0, strBuff,256,b->dbcc_name,sizeof(b->dbcc_name)); OutputMessage(hEditWnd, wParam, (LPARAM)b->dbcc_name); break; case DBT_DEVICEREMOVECOMPLETE: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: DBT_DEVICEREMOVECOMPLETE\n"), msgCount); break; case DBT_DEVNODES_CHANGED: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: DBT_DEVNODES_CHANGED\n"), msgCount); break; default: msgCount++; StringCchPrintf( strBuff, 256, TEXT("Message %d: WM_DEVICECHANGE message received, value %d unhandled.\n"), msgCount, wParam); break; } OutputMessage(hEditWnd, wParam, (LPARAM)strBuff); } break; case WM_CLOSE: if ( ! UnregisterDeviceNotification(hDeviceNotify) ) { ErrorHandler(TEXT("UnregisterDeviceNotification")); } DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: // Send all other messages on to the default windows handler. lRet = DefWindowProc(hWnd, message, wParam, lParam); break; } return lRet; } #define WND_CLASS_NAME TEXT("SampleAppWindowClass") // // InitWindowClass // BOOL InitWindowClass() // Routine Description: // Simple wrapper to initialize and register a window class. // Parameters: // None // Return Value: // TRUE on success, FALSE on failure. // Note: // wndClass.lpfnWndProc and wndClass.lpszClassName are the // important unique values used with CreateWindowEx and the // Windows message pump. { WNDCLASSEX wndClass; wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0)); wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WinProcCallback); wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hIcon = LoadIcon(0,IDI_APPLICATION); wndClass.hbrBackground = CreateSolidBrush(RGB(192,192,192)); wndClass.hCursor = LoadCursor(0, IDC_ARROW); wndClass.lpszClassName = WND_CLASS_NAME; wndClass.lpszMenuName = NULL; wndClass.hIconSm = wndClass.hIcon; if ( ! RegisterClassEx(&wndClass) ) { ErrorHandler(TEXT("RegisterClassEx")); return FALSE; } return TRUE; } // // main // int __stdcall _tWinMain( HINSTANCE hInstanceExe, HINSTANCE, // should not reference this parameter PTSTR lpstrCmdLine, int nCmdShow ) { // // To enable a console project to compile this code, set // Project->Properties->Linker->System->Subsystem: Windows. // int nArgC = 0; PWSTR* ppArgV = CommandLineToArgvW(lpstrCmdLine, &nArgC); g_pszAppName = ppArgV[0]; if ( ! InitWindowClass() ) { // InitWindowClass displays any errors return -1; } // Main app window HWND hWnd = CreateWindowEx( WS_EX_CLIENTEDGE | WS_EX_APPWINDOW, WND_CLASS_NAME, g_pszAppName, WS_OVERLAPPEDWINDOW, // style CW_USEDEFAULT, 0, 640, 480, NULL, NULL, hInstanceExe, NULL); if ( hWnd == NULL ) { ErrorHandler(TEXT("CreateWindowEx: main appwindow hWnd")); return -1; } // Actually draw the window. ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); // The message pump loops until the window is destroyed. MessagePump(hWnd); return 1; } // // OutputMessage // void OutputMessage( HWND hOutWnd, WPARAM wParam, LPARAM lParam ) // Routine Description: // Support routine. // Send text to the output window, scrolling if necessary. // Parameters: // hOutWnd - Handle to the output window. // wParam - Standard windows message code, not used. // lParam - String message to send to the window. // Return Value: // None // Note: // This routine assumes the output window is an edit control // with vertical scrolling enabled. // This routine has no error checking. { LRESULT lResult; LONG bufferLen; LONG numLines; LONG firstVis; // Make writable and turn off redraw. lResult = SendMessage(hOutWnd, EM_SETREADONLY, FALSE, 0L); lResult = SendMessage(hOutWnd, WM_SETREDRAW, FALSE, 0L); // Obtain current text length in the window. bufferLen = SendMessage (hOutWnd, WM_GETTEXTLENGTH, 0, 0L); numLines = SendMessage (hOutWnd, EM_GETLINECOUNT, 0, 0L); firstVis = SendMessage (hOutWnd, EM_GETFIRSTVISIBLELINE, 0, 0L); lResult = SendMessage (hOutWnd, EM_SETSEL, bufferLen, bufferLen); // Write the new text. lResult = SendMessage (hOutWnd, EM_REPLACESEL, 0, lParam); // See whether scrolling is necessary. if (numLines > (firstVis + 1)) { int lineLen = 0; int lineCount = 0; int charPos; // Find the last nonblank line. numLines--; while(!lineLen) { charPos = SendMessage( hOutWnd, EM_LINEINDEX, (WPARAM)numLines, 0L); lineLen = SendMessage( hOutWnd, EM_LINELENGTH, charPos, 0L); if(!lineLen) numLines--; } // Prevent negative value finding min. lineCount = numLines - firstVis; lineCount = (lineCount >= 0) ? lineCount : 0; // Scroll the window. lResult = SendMessage( hOutWnd, EM_LINESCROLL, 0, (LPARAM)lineCount); } // Done, make read-only and allow redraw. lResult = SendMessage(hOutWnd, WM_SETREDRAW, TRUE, 0L); lResult = SendMessage(hOutWnd, EM_SETREADONLY, TRUE, 0L); } // // ErrorHandler // void ErrorHandler( LPTSTR lpszFunction ) // Routine Description: // Support routine. // Retrieve the system error message for the last-error code // and pop a modal alert box with usable info. // Parameters: // lpszFunction - String containing the function name where // the error occurred plus any other relevant data you'd // like to appear in the output. // Return Value: // None // Note: // This routine is independent of the other windowing routines // in this application and can be used in a regular console // application without modification. { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the error message and exit the process. lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction)+40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, g_pszAppName, MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); }
上面的代码改编自 MSDN :http://msdn.microsoft.com/en-us/library/windows/desktop/aa363432(v=vs.85).aspx
运行结果
此外,本文还参考了如下文章
http://blog.csdn.net/daoxwj/article/details/8819784
http://www.codeproject.com/Articles/14500/Detecting-Hardware-Insertion-and-or-Removal
下载
vcusb
在Console中使用Timer (2)
之前的一篇文章展示了如何在Console中使用Timer,他使用的是CallBack方式进行回调的。这里演示直接处理 WM_TIMER 的方法,代码如下
#include “stdafx.h”
#include
#include
#include
int count =0;
VOID ShowTimer()
{
count++;
printf(“WM_TIMER in work thread count=%d\n”,count);
}
DWORD CALLBACK Thread(PVOID pvoid)
{
MSG msg;
UINT timerid=SetTimer(NULL,111,3000,NULL);
BOOL bRet;
PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE);
while((bRet = GetMessage(&msg,NULL,0,0))!= 0)
{
if(bRet==-1)
{
// handle the error and possibly exit
}
else
{
if (msg.message == WM_TIMER) { ShowTimer(); }
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
KillTimer(NULL,timerid);
printf(“thread end here\n”);
return 0;
}
int main()
{
DWORD dwThreadId;
printf(“Use timer in workthread of console application\n”);
HANDLE hThread = CreateThread(NULL,0,Thread,0,0,&dwThreadId);
_getch();
return 0;
}
运行结果和之前的相同。
代码和EXE在这里下载
另外,还有如下的一个例子,来自 http://read.pudn.com/downloads121/sourcecode/windows/console/512780/1ms/1ms.cpp__.htm
//************************************************************************************
//本程序使用了两种实现定时的方法,都是基于API的,而不是MFC
//
// 1. 是使用线程定时休眠的方法,启动线程ThreadProc,在线程中输出,然后Sleep 1000ms
//
// 2. 使用定时器方法,设置一个1000ms的定时器(SetTimer),然后捕捉该消息,然后调用回调函数
// TimerProc,在该函数中输出DEF,注意,SetTimer可以直接写回调函数地址,不必捕捉消息。
// 3. 本例子已经很详细了。
// 4. 祝你好运。
//
//************************************************************************************
#include “stdafx.h”
#include
DWORD WINAPI ThreadProc( LPVOID lpParameter )//方法1
{
static DWORD tick=0;
DWORD tmp = GetTickCount();
while(1)
{
tick = GetTickCount()-tmp;//获得系统从启动开始到现在的ms数
tmp = GetTickCount();
printf(“THREAD_PROC: abc %d, tickcount: %d\n”,tick,tmp);//打印abc和上次打印到这次打印之间的毫秒间隔。
Sleep(1000);//每隔1000ms打印abc
}
}
VOID TimerProc()//方法2
{
static DWORD tick=0;
static DWORD tmp = GetTickCount();
tick = GetTickCount()-tmp;
tmp = GetTickCount();
printf(” TimerProc________________def %d\n”,tick);
}
int main()
{
DWORD dwthread;
::CreateThread(NULL,0,ThreadProc,(LPVOID)0,1024,&dwthread);//生成一个线程,在该线程里每1000ms输出一个”abc”,然后SLEEP
SetTimer(0,0,1000,0);//设置一个定时器,定时器的回调函数为0,仅产生定时器消息,在main函数里捕捉该消息
MSG msg;
bool flag;
while(1)//该循环捕捉定时器消息,并且防止main函数退出
{
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
while( (flag = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (flag == -1)
{
// handle the error and possibly exit
}
else if(msg.message==WM_TIMER)
{
TimerProc();//如果是定时器消息,调用timerproc
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
}
关于监视插入U盘的问题(1)
本文是参考 http://bbs.csdn.net/topics/390293365?page=1#post-393016986 完成的。
修改了其中的Demo,使得程序能够在 VS2008 Express 下编译成功。
修改后的代码如下,删除了读取识别出来盘符上指定文件的代码
//编程识别u盘的插入,通过处理WM_DEVICECHANGE的消息,来达到识别的效果
//vc下编译通过,能够识别
#include “stdafx.h”
#include
#include
#include
#include
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
TCHAR FirstDriveFromMask (ULONG unitmask);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//windows窗口类的成员
TCHAR szClassName[] = TEXT(“MainWClass”);
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = ::LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = ::LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szClassName;
wndclass.hIconSm = NULL;
::RegisterClassEx(&wndclass);
HWND hwnd = ::CreateWindowEx(
0,
szClassName,
TEXT(“mc”),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
UINT Cret = GetLastError();
//printf(“%d\n”,GetLastError());
if (hwnd == NULL)
{
::MessageBox(NULL,TEXT(“Create Window error!”),TEXT(“error”),MB_OK);
return -1;
}
::ShowWindow(hwnd,nCmdShow);
::UpdateWindow(hwnd);
MSG msg;
while (::GetMessage(&msg,NULL,0,0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return msg.wParam;
}
//回调函数处理消息
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:/*初始化*/
MessageBox(hwnd, TEXT(“go!”), TEXT(“405 Studio”), MB_OK);
break;
case WM_DEVICECHANGE:
if(wParam == DBT_DEVICEARRIVAL) //设备激活
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
TCHAR szMsg[80],Disk;
Disk = FirstDriveFromMask(lpdbv ->dbcv_unitmask);
wsprintf (szMsg,TEXT(“Drive %c: Media has arrived./n”),Disk);
MessageBox (hwnd, szMsg, TEXT(“WM_DEVICECHANGE”), MB_OK);
//Sleep(1000);
::PostQuitMessage(0);
}
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
return 0;
}
//提取u盘的盘符
TCHAR FirstDriveFromMask (ULONG unitmask)
{
char i;
for (i = 0; i < 26; ++i)
{
if (unitmask & 0x1)
break;
unitmask = unitmask >> 1;
}
return (i + ‘A’);
}
首先运行本程序,然后插入U盘,可以看出识别出来插入U盘的盘符,另外弹出来的是Windows自动播放的对话框。运行结果如下:
源程序和编译后的EXE可以从下面下载
在Console中使用Timer (1)
本文内容来自 http://biancheng.dnbcw.info/60/60901.html 是在一个控制台窗口中创建一个线程,然后在线程中处理Timer的消息
整理后的代码如下,VC2008 Express编译通过
#include “stdafx.h”
#include
#include
#include
int count =0;
VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
count++;
printf(“WM_TIMER in work thread count=%d\n”,count);
}
DWORD CALLBACK Thread(PVOID pvoid)
{
MSG msg;
UINT timerid=SetTimer(NULL,111,3000,TimerProc);
BOOL bRet;
PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE);
while((bRet = GetMessage(&msg,NULL,0,0))!= 0)
{
if(bRet==-1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
KillTimer(NULL,timerid);
printf(“thread end here\n”);
return 0;
}
int main()
{
DWORD dwThreadId;
printf(“Use timer in workthread of console application\n”);
HANDLE hThread = CreateThread(NULL,0,Thread,0,0,&dwThreadId);
_getch();
return 0;
}
运行结果
下载 ConTimer
旧事重提:理解状态机
最近在看编译原理方面的东西,状态机是很重要的部分。之前遇到过一个问题,用这个问题让我深刻的理解了状态机。当年写了这篇文章,但是看起来这次更新忘记上传了。现在补上这篇文章。具体的问题是这样的:
“我不是计算机专业毕业的,也没有研究过离散数学(听说状态机属于离散数学)。前几天刚好有机会听别人讲这方面的问题,于是针对这个题目研究了一下。记录与此。
一.问题
请画出车库门控制器的 FSM(finite state machine)。车库门的功能如下:
1. 开启车库门
2. 关闭车库门
3. 车库门进行中(正在开启或关闭中)停止
4. 当车库门是处于第 3 点的状态时,往(停止前)反方向运行
PS:以上这些功能只须使用一个控制键”
解决方法和分析的过程在PDF 中能找到。