• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            在 Windows CE 下自帶有無線網卡的配置和連接程序,可是我的系統剪裁掉了資源管理器和任務欄,導致自帶的無線網卡配置程序不能再使用了,只好自力更生。

            我的環境是 S3C2440 + WinCE 5.0 + VNUWCL5(威盛無線網卡)及驅動程序。使用 Automatic Configuration Functions API

            一、枚舉系統中可用的無線網絡設備

                  下面的函數可以枚舉出系統中所有可用的無線網卡設備的GUID,為了簡化,我選擇第一塊可用的無線網卡來操作      

            BOOL GetFirstWirelessCard(PTCHAR pCard)
            {
            if (!pCard)
            {
            return FALSE;
            }
            INTFS_KEY_TABLE IntfsTable;
            IntfsTable.dwNumIntfs = 0;
            IntfsTable.pIntfs = NULL;
            _tcscpy(pCard, TEXT(""));
            // 枚舉系統中可用的無線網卡
            DWORD dwStatus = WZCEnumInterfaces(NULL, &IntfsTable);
            if (dwStatus != ERROR_SUCCESS)
            {
            RETAILMSG(DBG_MSG, (TEXT("WZCEnumInterfaces() error 0x%08X\n"),dwStatus));
            return FALSE;
            }
            // 判斷無線網卡的數量,可以根據無線網卡數量來枚舉出所有可用的無線網卡
            if (!IntfsTable.dwNumIntfs)
            {
            RETAILMSG(DBG_MSG, (TEXT("System has no wireless card.\n")));
            return FALSE;
            }
            _tcscpy(pCard, IntfsTable.pIntfs[0].wszGuid);
            LocalFree(IntfsTable.pIntfs);
            return TRUE;
            }

             二、獲取無線網絡信息

                    獲取到了系統可用的無線網卡后,我們就可以利用它的 GUID 號來進行進一步的操作了,首先要做的事情就是得到該無線網卡的信息以及該無線網卡掃描到的 WIFI 網關信息。

                    以下函數可以獲取到該無線網卡及掃描的到的無線 AP 信息

            //////////////////////////////////////////////////////////////////////////
            // pCard: 無線網卡GUID
            // pIntf: 無線網卡配置信息結果體
            // pOutFlags: 網卡配置信息掩碼標志
            //////////////////////////////////////////////////////////////////////////
            BOOL GetWirelessCardInfo(PTCHAR pCard, PINTF_ENTRY_EX pIntf, PDWORD pOutFlags)
            {
            TCHAR *szWiFiCard = NULL;
            // 參數校驗
            if (!pCard || !pIntf || !pOutFlags)
            {
            RETAILMSG(DBG_MSG, (TEXT("Param Error.\n")));
            return FALSE;
            }
            szWiFiCard = pCard;
            *pOutFlags = 0;
            // 初始化無線網卡信息
            ZeroMemory(pIntf, sizeof(INTF_ENTRY_EX));
            // 設置GUID 號
            pIntf->wszGuid = szWiFiCard;
            // 查詢無線網卡信息
            DWORD dwStatus = WZCQueryInterfaceEx(NULL, INTF_ALL, pIntf, pOutFlags);
            if (dwStatus != ERROR_SUCCESS)
            {
            RETAILMSG(DBG_MSG, (TEXT("WZCQueryInterfaceEx() error 0x%08X\n"), dwStatus));
            return FALSE;
            }
            return TRUE;
            }

            三、判斷連接狀態

                    我們可以通過無線網卡的狀態來判斷當前無線網卡是否已經和無線AP建立了連接

            BOOL IsAssociated(const INTF_ENTRY_EX Intf, const DWORD dwOutFlags)
            {
            if (dwOutFlags & INTF_BSSID)
            {
            PRAW_DATA prdMAC = (PRAW_DATA)(&Intf.rdBSSID);
            // 判斷BSSID 的MAC 地址是否有效來判斷是否和無線AP建立了連接
            if (prdMAC == NULL || prdMAC->dwDataLen == 0 ||
            (!prdMAC->pData[0] && !prdMAC->pData[1] && !prdMAC->pData[2] &
            !prdMAC->pData[3] && !prdMAC->pData[4] && !prdMAC->pData[5]))
            {
            RETAILMSG(DBG_MSG, (TEXT("(This wifi card is not associated to any)\n")));
            return FALSE;
            }
            else
            {
            RETAILMSG(DBG_MSG, (TEXT("(This wifi card is associated state)\n")));
            return TRUE;
            }
            }
            else
            {
            return FALSE;
            }
            }

            四、獲取無線AP信息

                    獲取了無線網卡的信息后,可以通過無線網卡枚舉出當前所有可用的無線AP的SSID名稱以及加密模式等等所有可用信息,一下函數可以實現該功能

            void GetWirelseeListSSID(const PRAW_DATA prdBSSIDList, HWND hListCtlWnd)
            {
            if (prdBSSIDList == NULL || prdBSSIDList->dwDataLen  == 0)
            {
            RETAILMSG(DBG_MSG, (TEXT("<null> entry.\n")));
            }
            else
            {
            PWZC_802_11_CONFIG_LIST pConfigList = (PWZC_802_11_CONFIG_LIST)prdBSSIDList->pData;
            //RETAILMSG(DBG_MSG, (TEXT("[%d] entries.\n"), pConfigList->NumberOfItems));
            uint i;
            // 枚舉所有無線AP
            for (i = 0; i < pConfigList->NumberOfItems; i++)
            {
            PWZC_WLAN_CONFIG pConfig = &(pConfigList->Config[i]);
            RAW_DATA rdBuffer;
            rdBuffer.dwDataLen = pConfig->Ssid.SsidLength;
            rdBuffer.pData = pConfig->Ssid.Ssid;
            TCHAR tSsid[MAX_PATH];
            // 將SSID 的ASCII 碼轉化成字符串
            PrintSSID(&rdBuffer, tSsid);
            if (hListCtlWnd)
            {
            if (ListBox_FindString(hListCtlWnd, 0, tSsid) == LB_ERR)
            {
            ListBox_AddString(hListCtlWnd, tSsid);
            }
            }
            //RETAILMSG(DBG_MSG, (TEXT("\n")));
            }
            }
            }

            五、連接到指定的無線AP

            //////////////////////////////////////////////////////////////////////////
            // pCard: 無線網卡GUID
            // pSSID: 無線AP SSID號
            // bAdhoc: 是否點對點的WIFI 連接
            // ulPrivacy: 加密模式(WEP/WPA....)
            // ndisMode: 認證模式(Open/Share)
            // iKeyIndex: 密鑰索引(1-4)
            // pKey: 密碼
            // iEapType: 802.11 認證模式
            //////////////////////////////////////////////////////////////////////////
            BOOL WirelessConnect(PTCHAR pCard, PTCHAR pSSID, BOOL bAdhoc, ULONG ulPrivacy, NDIS_802_11_AUTHENTICATION_MODE ndisMode, int iKeyIndex, PTCHAR pKey, int iEapType)
            {
            BOOL bRet = FALSE;
            if (!pSSID)
            {
            RETAILMSG(DBG_MSG, (TEXT("Param Error.\n")));
            return FALSE;
            }
            else
            {
            WZC_WLAN_CONFIG wzcConfig;
            ZeroMemory(&wzcConfig, sizeof(WZC_WLAN_CONFIG));
            wzcConfig.Length = sizeof(WZC_WLAN_CONFIG);
            wzcConfig.dwCtlFlags = 0;
            wzcConfig.Ssid.SsidLength = _tcslen(pSSID);
            for (UINT i = 0; i < wzcConfig.Ssid.SsidLength; i++)
            {
            wzcConfig.Ssid.Ssid[i] = (CHAR)pSSID[i];
            }
            if (bAdhoc)
            {
            wzcConfig.InfrastructureMode = Ndis802_11IBSS;
            }
            else
            {
            wzcConfig.InfrastructureMode = Ndis802_11Infrastructure;
            }
            wzcConfig.AuthenticationMode = ndisMode;
            wzcConfig.Privacy = ulPrivacy;
            if (pKey == NULL || _tcslen(pKey) == 0)
            {
            // 對密鑰進行轉換
            bRet = InterpretEncryptionKeyValue(wzcConfig, 0, NULL, TRUE);
            wzcConfig.EapolParams.dwEapType = iEapType;
            wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;
            wzcConfig.EapolParams.bEnable8021x  = TRUE;
            wzcConfig.EapolParams.dwAuthDataLen = 0;
            wzcConfig.EapolParams.pbAuthData = 0;
            }
            else
            {
            RETAILMSG(DBG_MSG, (TEXT("WirelessConnect iKeyIndex = %d.\n"), iKeyIndex));
            bRet = InterpretEncryptionKeyValue(wzcConfig, iKeyIndex, pKey, FALSE);
            }
            // 連接到指定的無線AP,并將該AP添加到首先無線AP中
            AddToPreferredNetworkList(pCard, wzcConfig, pSSID);
            }
            return bRet;
            }

            六、密鑰轉換

                    輸入的密鑰需要通過加密方式進行一定的轉化,以下函數可以完成改功能

            static void EncryptWepKMaterial(IN OUT WZC_WLAN_CONFIG* pwzcConfig)
            {
            BYTE chFakeKeyMaterial[] = { 0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66 };
            for (int i = 0; i < WZCCTL_MAX_WEPK_MATERIAL; i++)
            pwzcConfig->KeyMaterial[i] ^= chFakeKeyMaterial[(7*i)%13];
            }
            BOOL InterpretEncryptionKeyValue(IN OUT WZC_WLAN_CONFIG& wzcConfig, IN int iKeyIndex, IN PTCHAR pKey, IN BOOL bNeed8021X)
            {
            if(wzcConfig.Privacy == Ndis802_11WEPEnabled)
            {
            if(!bNeed8021X && pKey)
            {
            wzcConfig.KeyIndex = iKeyIndex;
            wzcConfig.KeyLength = _tcslen(pKey);
            if((wzcConfig.KeyLength == 5) || (wzcConfig.KeyLength == 13))
            {
            for(UINT i=0; i<wzcConfig.KeyLength; i++)
            wzcConfig.KeyMaterial[i] = (UCHAR)pKey[i];
            }
            else
            {
            if((pKey[0] != TEXT('0')) || (pKey[1] != TEXT('x')))
            {
            RETAILMSG(DBG_MSG, (TEXT("Invalid key value.\n")));
            return FALSE;
            }
            pKey += 2;
            wzcConfig.KeyLength = wcslen(pKey);
            if((wzcConfig.KeyLength != 10) && (wzcConfig.KeyLength != 26))
            {
            RETAILMSG(DBG_MSG, (TEXT("Invalid key value.\n")));
            return FALSE;
            }
            wzcConfig.KeyLength >>= 1;
            for(UINT i=0; i<wzcConfig.KeyLength; i++)
            {
            wzcConfig.KeyMaterial[i] = (HEX(pKey[2 * i]) << 4) | HEX(pKey[2 * i + 1]);
            }
            }
            EncryptWepKMaterial(&wzcConfig);
            wzcConfig.dwCtlFlags |= WZCCTL_WEPK_PRESENT;
            }
            }
            else if(wzcConfig.Privacy == Ndis802_11Encryption2Enabled
            || wzcConfig.Privacy == Ndis802_11Encryption3Enabled)
            {
            if(!bNeed8021X)
            {
            wzcConfig.KeyLength = wcslen(pKey);
            if((wzcConfig.KeyLength < 8) || (wzcConfig.KeyLength > 63))
            {
            RETAILMSG(DBG_MSG, (TEXT("WPA-PSK/TKIP key should be 8-63 char long string.\n")));
            return FALSE;
            }
            char szEncryptionKeyValue8[64]; // longest key is 63
            memset(szEncryptionKeyValue8, 0, sizeof(szEncryptionKeyValue8));
            WideCharToMultiByte(CP_ACP,
            0,
            pKey,
            wzcConfig.KeyLength + 1,
            szEncryptionKeyValue8,
            wzcConfig.KeyLength + 1,
            NULL,
            NULL);
            WZCPassword2Key(&wzcConfig, szEncryptionKeyValue8);
            EncryptWepKMaterial(&wzcConfig);
            wzcConfig.dwCtlFlags |= WZCCTL_WEPK_XFORMAT
            | WZCCTL_WEPK_PRESENT
            | WZCCTL_ONEX_ENABLED;
            }
            wzcConfig.EapolParams.dwEapFlags = EAPOL_ENABLED;
            wzcConfig.EapolParams.dwEapType = DEFAULT_EAP_TYPE;
            wzcConfig.EapolParams.bEnable8021x = TRUE;
            wzcConfig.WPAMCastCipher = Ndis802_11Encryption2Enabled;
            }
            return TRUE;
            }

                  通過以上操作,完全可以連接到可用的無線AP了,再加上些適當的UI程序,完全可以用來替代 Windows CE 自帶的無線配置程序了,我再連接中放置了一個簡單的而完整的測試程序,相信大家看了以后都知道怎么操作無線網卡了

            http://download.csdn.net/source/927575

            posted @ 2010-12-16 09:31 wrh 閱讀(1659) | 評論 (0)編輯 收藏
            Note:需CE4.0或更高版本(兼容NDIS5.1)支持
            一、加入頭文件
            #include <winioctl.h>
            #include <ntddndis.h>
            #include <nuiouser.h>
            
            二、Attach to NDISUIO
            HANDLE hNdis = ::CreateFile( NDISUIO_DEVICE_NAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
            (HANDLE)INVALID_HANDLE_VALUE );

            三、獲取設備名稱

            UCHAR                  cbQueryBuffer[ 1024 ];
            PNDISUIO_QUERY_BINDING pQueryBinding;
            DWORD                  dwBytesReturned = 0;
            pQueryBinding = (PNDISUIO_QUERY_BINDING)&cbQueryBuffer[ 0 ];
            pQueryBinding->BindingIndex = 0;
            if ( ::DeviceIoControl( hNdis,
            IOCTL_NDISUIO_QUERY_BINDING,
            (LPVOID)&cbQueryBuffer[ 0 ],
            sizeof(NDISUIO_QUERY_BINDING),
            (LPVOID)&cbQueryBuffer[ 0 ],
            sizeof(cbQueryBuffer),
            &dwBytesReturned,
            NULL ) == TRUE )
            {
            TCHAR* pDeviceName = (TCHAR*)( cbQueryBuffer + pQueryBinding->DeviceNameOffset );
            }

             

            四、檢測連接狀態

            NIC_STATISTICS nicStatistics = { 0 };
            DWORD          dwBytesReturned = 0;
            BOOL bConnected = FALSE;
            nicStatistics.ptcDeviceName = pDeviceName;
            if ( ::DeviceIoControl( hNdis,
            IOCTL_NDISUIO_NIC_STATISTICS,
            NULL,
            0,
            &nicStatistics,
            sizeof(NIC_STATISTICS),
            &dwBytesReturned,
            NULL ) == TRUE )
            {
            bConnected = ( nicStatistics.MediaState == MEDIA_STATE_CONNECTED );
            }

            五、獲取信號強度

            // example.
            // < -90 : No Signal
            // < -81 : Very Low
            // < -71 : Low
            // < -67 : Good
            // < -57 : Very Good
            // ...   : Excellent
            NDISUIO_QUERY_OID ndisQueryOid = { 0 };
            DWORD             dwBytesReturned = 0;
            int nDb = 0;
            ndisQueryOid.Oid = OID_802_11_RSSI;
            ndisQueryOid.ptcDeviceName = pDeviceName;
            if ( ::DeviceIoControl( hNdis,
            IOCTL_NDISUIO_QUERY_OID_VALUE,
            (LPVOID)&ndisQueryOid,
            sizeof(ndisQueryOid),
            (LPVOID)&ndisQueryOid,
            sizeof(ndisQueryOid),
            &dwBytesReturned,
            NULL ) == TRUE )
            {
            ::CopyMemory( &nDb, &ndisQueryOid.Data[ 0 ], sizeof(ULONG) );
            }
            posted @ 2010-12-16 09:12 wrh 閱讀(1751) | 評論 (1)編輯 收藏


            http://msdn.microsoft.com/en-us/library/ms706716(VS.85).aspx

            The WlanEnumInterfaces function enumerates all of the wireless LAN interfaces currently enabled on the local computer.

            Syntax

            DWORD WINAPI WlanEnumInterfaces(
            __in        HANDLE hClientHandle,
            __reserved  PVOID pReserved,
            __out       PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
            );
            

            Parameters

            hClientHandle [in]

            The client's session handle, obtained by a previous call to the WlanOpenHandle function.

            pReserved [in]

            Reserved for future use. This parameter must be set to NULL.

            ppInterfaceList [out]

            A pointer to storage for a pointer to receive the returned list of wireless LAN interfaces in a WLAN_INTERFACE_INFO_LIST structure.

            The buffer for the WLAN_INTERFACE_INFO_LIST returned is allocated by the WlanEnumInterfaces function if the call succeeds.

            Return Value

            If the function succeeds, the return value is ERROR_SUCCESS.

            If the function fails, the return value may be one of the following return codes.

            Return code Description
            ERROR_INVALID_PARAMETER

            A parameter is incorrect. This error is returned if the hClientHandle or ppInterfaceList parameter is NULL. This error is returned if the pReserved is not NULL. This error is also returned if the hClientHandle parameter is not valid.

            ERROR_INVALID_HANDLE

            The handle hClientHandle was not found in the handle table.

            RPC_STATUS

            Various error codes.

            ERROR_NOT_ENOUGH_MEMORY

            Not enough memory is available to process this request and allocate memory for the query results.

             

            Remarks

            The WlanEnumInterfaces function allocates memory for the list of returned interfaces that is returned in the buffer pointed to by the ppInterfaceList parameter when the function succeeds. The memory used for the buffer pointed to by ppInterfaceList parameter should be released by calling the WlanFreeMemory function after the buffer is no longer needed.

            Examples

            The following example enumerates the wireless LAN interfaces on the local computer and prints values from the retrieved WLAN_INTERFACE_INFO_LIST structure and the enumerated WLAN_INTERFACE_INFO structures.

            Note  This example will fail to load on Windows Server 2008 and Windows Server 2008 R2 if the Wireless LAN Service is not installed and started.

            #ifndef UNICODE
            #define UNICODE
            #endif
            #include <windows.h>
            #include <wlanapi.h>
            #include <objbase.h>
            #include <wtypes.h>
            #include <stdio.h>
            #include <stdlib.h>
            // Need to link with Wlanapi.lib and Ole32.lib
            #pragma comment(lib, "wlanapi.lib")
            #pragma comment(lib, "ole32.lib")
            int wmain()
            {
            // Declare and initialize variables.
            HANDLE hClient = NULL;
            DWORD dwMaxClient = 2;   //
            DWORD dwCurVersion = 0;
            DWORD dwResult = 0;
            int iRet = 0;
            WCHAR GuidString[40] = {0};
            int i;
            /* variables used for WlanEnumInterfaces  */
            PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
            PWLAN_INTERFACE_INFO pIfInfo = NULL;
            dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);
            if (dwResult != ERROR_SUCCESS)  {
            wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
            // FormatMessage can be used to find out why the function failed
            return 1;
            }
            dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
            if (dwResult != ERROR_SUCCESS)  {
            wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);
            // FormatMessage can be used to find out why the function failed
            return 1;
            }
            else {
            wprintf(L"Num Entries: %lu\n", pIfList->dwNumberOfItems);
            wprintf(L"Current Index: %lu\n", pIfList->dwIndex);
            for (i = 0; i < (int) pIfList->dwNumberOfItems; i++) {
            pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];
            wprintf(L"  Interface Index[%d]:\t %lu\n", i, i);
            iRet = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, 39);
            // For c rather than C++ source code, the above line needs to be
            // iRet = StringFromGUID2(&pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, 39);
            if (iRet == 0)
            wprintf(L"StringFromGUID2 failed\n");
            else {
            wprintf(L"  InterfaceGUID[%d]: %ws\n",i, GuidString);
            }
            wprintf(L"  Interface Description[%d]: %ws", i,
            pIfInfo->strInterfaceDescription);
            wprintf(L"\n");
            wprintf(L"  Interface State[%d]:\t ", i);
            switch (pIfInfo->isState) {
            case wlan_interface_state_not_ready:
            wprintf(L"Not ready\n");
            break;
            case wlan_interface_state_connected:
            wprintf(L"Connected\n");
            break;
            case wlan_interface_state_ad_hoc_network_formed:
            wprintf(L"First node in a ad hoc network\n");
            break;
            case wlan_interface_state_disconnecting:
            wprintf(L"Disconnecting\n");
            break;
            case wlan_interface_state_disconnected:
            wprintf(L"Not connected\n");
            break;
            case wlan_interface_state_associating:
            wprintf(L"Attempting to associate with a network\n");
            break;
            case wlan_interface_state_discovering:
            wprintf(L"Auto configuration is discovering settings for the network\n");
            break;
            case wlan_interface_state_authenticating:
            wprintf(L"In process of authenticating\n");
            break;
            default:
            wprintf(L"Unknown state %ld\n", pIfInfo->isState);
            break;
            }
            wprintf(L"\n");
            }
            }
            if (pIfList != NULL) {
            WlanFreeMemory(pIfList);
            pIfList = NULL;
            }
            return 0;
            }
            

            Requirements

            Minimum supported client

            Windows Vista, Windows XP with SP3

            Minimum supported server

            Windows Server 2008

            Redistributable

            Wireless LAN API for Windows XP with SP2

            Header

            Wlanapi.h (include Wlanapi.h)

            Library

            Wlanapi.lib

            DLL

            Wlanapi.dll
            posted @ 2010-12-16 09:01 wrh 閱讀(2657) | 評論 (0)編輯 收藏
            用native wifi api吧。
            VS2008下:
            加入:
            #include "Wlanapi.h"
            #pragma comment(lib, "Wlanapi.lib")
            變量:
            DWORD pdwNegotiatedVersion;
            HANDLE phClientHandle;
            PWLAN_INTERFACE_INFO_LIST wiiList;
            然后用下面語句打開handle.
            WlanOpenHandle (1,NULL,&pdwNegotiatedVersion,&phClientHandle);
            用WlanEnumInterfaces來枚舉interfaces到一個WLAN_INTERFACE_INFO_LIST結構。如下:
            WlanEnumInterfaces(phClientHandle,NULL,&wiiList);
            然后wiiList->dwNumberOfItems的值就是無線網卡的數量。
            VC6的時候沒有Wlanapi.h頭文件。可以直接LoadLibrary("wlanapi.dll"),然后GetProcAddress取得以上兩個函數指針。














            #include <windows.h>
            #include <stdio.h>
            int main()
            {
            HKEY bKey,hKey;
            LONG retVal;
            DWORD dwBuf = 1;
            DWORD dwLen;
            char SubKey[] = "System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
            char SubKeyValueName[] = "MediaSubType";
            bKey = HKEY_LOCAL_MACHINE;
            retVal = RegOpenKeyEx(bKey,SubKey,0,KEY_ALL_ACCESS,&hKey);
            if(retVal!=ERROR_SUCCESS)
            {
            return -1;
            }
            RegQueryValueEx( bKey, SubKeyValueName, 0, 0, (LPBYTE)&dwBuf, &dwLen );
            if ( dwBuf == 1 )
            printf( "普通網卡\n " );
            if ( dwBuf == 2 )
            printf( "無線網卡\n " );
            return 0;
            }
            posted @ 2010-12-16 08:45 wrh 閱讀(2163) | 評論 (0)編輯 收藏

            轉載文章一:http://www.cnblogs.com/shanhaobo/articles/1065380.html

            [3D基礎]理解計算機3D圖形學中的坐標系變換

                 要談坐標系變換,那么坐標系有哪些呢?依次有:物體坐標系,世界坐標系,相機坐標系,投影坐標系以及屏幕坐標系.我要討論的就是這些坐標系間的轉換。
                 這些坐標系不是憑空而來,他們都是為了完成計算機3D圖形學最最最基本的目標而出現.
                  計算機3D圖形學最最最基本的目標就是:將構建好的3D物體顯示在2D屏幕坐標上.
                  初看好像就是將最初的物體坐標系轉換到屏幕坐標系就可以了呀,為什么多出了世界坐標系,相機坐標系,投影坐標 系。這是因為:在一個大世界里有多個物體,而每個物體都有自己的坐標系,如何表述這些物體間相對的關系,這個多出了世界坐標系;如果只需要看到這個世界其 中一部分,這里就多出了相機坐標系;至于投影坐標系那是因為直接將3D坐標轉換為屏幕坐標是非常復雜的(因為它們不僅維度不同,度量不同(屏幕坐標一般都 是像素為單位,3D空間中我們可以現實世界的米,厘米為單位),XY的方向也不同,在2D空間時還要進行坐標系變換),所以先將3D坐標降維到2D坐標, 然后2D坐標轉換到屏幕坐標。
            理解3D圖形學的第一步:理解左手坐標系與右手坐標系
                  為什么會有左手坐標系與右手坐標系之分?
                  在3D空間(沒錯!就是3D)中,所有2D坐標系是等價的(就是通過一系列的仿射變換,可以互相轉換)
                  而3D坐標系不是等價的,通過仿射變換,是無法將左手坐標系轉換到右手坐標系;也就是說,物體坐標系用的就是左手坐標系,世界坐標系用的是右手 坐標系,那么物體可能就是不會是我們所希望的樣子了,可能是倒立的,也可能是背對著我們的,所以我們要區分左手坐標系與右手坐標系。也許在4D空間,左右 手坐標系就可以互相變換了吧。
                  進入正題吧:
                 首先討論的是物體坐標系->世界坐標系
                  前面說了為了描述多個物體間相對的關系,這里引進了世界坐標系,所以世界坐標系是個參考坐標系。
                  這一步的目的將所有的物體的點都轉移到世界坐標系,這里主要涉及的是旋轉,縮放,平移等。
                  不過我將詳細說明為何及如何用矩陣來描述這些變換。
                  例:如果有兩個坐標系C與C`, C`是C繞Z軸旋轉θ得到的。下面是各坐標軸的變換:
                         
                 如果是C坐標系的點P(x, y, z),而在C`的表示就是
               
                 這時該如何建立矩陣呢? 答案就是區分你用的是行向量還是列向量.也許有人會問為什么不區分是左手坐標系還是右手坐標系呢?因為C可以變換到C`,那么他們一定是同在左手坐標系或右手坐標系,變換只能在可以互相轉換的坐標系之間進行。
                  如果你用的是行向量:由于行向量只能左乘矩陣(注意乘與乘以的區別)
                  所以矩陣形式應該是這樣
                
                 只有這樣,在左乘矩陣時才能得到上面P`的形式。
                
                 如果你用的是列向量: 由于列向量只能右乘矩陣(注意乘與乘以的區別)
                 所以矩陣形式應該是這樣
                
                 只有這樣,在右乘矩陣時才能得到上面P`的形式。
              
                 至于如何旋轉,縮放,平移我不在多說。
                 …………………………………覺得自己好像跑題了.還好這兩個坐標系變換很簡單。
                 我們再討論世界坐標系->相機坐標系
                 引進相機的目的就是只需看到世界的一部分,而哪些是可以在相機里看到的,就需要進行篩選。將物體轉換到相機坐標系,這樣相機坐標系進行篩選時就會簡單很多。這里的重點是構建相機坐標系。
                 物體坐標系,世界坐標系是美工在繪制時就定義好了的。而相機坐標系是需要程序實時構建的。(當然這是通常情況下,如果你要建立一個世界,這個世界都是圍繞 你轉,要實時改變所有物體坐標系,固定相機坐標系(其實這時候相機坐標系就是世界坐標系),建立一個地心說的世界,我也沒辦法,你的思維也太不一樣了。)
                 如何構建相機坐標系呢?首先我們要明確目標:我們是要構建3D坐標系(好像是廢話),三個坐標軸要互相垂直(也好像是廢話).
                  我們一般用UVN相機。例如:D3D的D3DXMatrixLookAtLH,D3DXMatrixLookAtRH,OGL的gluLookAt(右手坐標系).
                  如何建立呢UVN相機呢? 我們就要利用叉積這個工具了:兩個不平行,不重疊的向量的叉積可以得到與這兩個向量互相垂直的向量。
                  如果有了相機的位置與目標的位置那么我們可以確定一個Z軸(有人問為什么是Z軸,因為物體的遠與近我們就習慣用Z值來表示的)。求Z軸時要注意 是左手坐標系還是右手坐標系,左右手坐標系XY軸方向相同時,Z軸的方向相反。所以左手坐標系是目標位置減去相機位置,而右手坐標系則是相機位置減去目標 位置。記得normalize
                 這是我們要得到X與Y軸了。如何求X,Y軸呢?
                 一般方法是:
                 1、選擇一個臨時Y軸,
                 2、對臨時Y 與Z 軸進行叉積求得一個X軸
                 3、X軸再與Z軸進行叉積,得到一個Y軸。
                 有了XYZ就可以求出旋轉的相機矩陣了。
                 如何選擇一個Y軸呢?大多數情況下是(0,1,0),但是如果是相機位置E與目標位置T垂直,即(E-T=(0,+/-1,0)時),這時就不能用(0,1,0)了, 因為兩個平行向量的叉積是零向量,所以我們就要另選一個Y軸。
                 但是我覺得我們可以改變方法。
                  如果不能選Y軸,我們就選擇一個臨時X軸,這個臨時X軸就是(1,0,0)。
                 然后再對臨時X軸與Z軸進行叉積求得一個Y軸。
                 最后Y軸再與Z軸進行叉積,得到X軸。
                  這樣可以得到XYZ軸。
                  最后再根據行向量與列向量建立相機矩陣,再進行平移。

                 相機坐標系->投影坐標系.
                 投影的目的就是:降維.
                  兩種投影方式:正交投影與透視投影.
                  在我們TEAM中易穎已經寫了,我就不多說了,大家去看他的文章。

                 投影坐標系->屏幕坐標系
                  這是最簡單的。2D坐標變換。也不多說。

            轉載文章2:http://www.xingousi.com/computer/computergraphics.htm

            計算機圖形學筆記(Part 1 ):計算機圖形學透視投影變換原理及一點和兩點透視

             

            一、平行互分法

            吳英凡所寫的《透視作圖的新方法——交點法體系》,其中談到的平行互分法,還是有道理的。

            其實簡單點說,就是透視圖上的兩條“原來空間中的平行線”(在畫面上透視投影為相交于滅點),通過其中一條透視投影直線的端點畫另一條透視投影直線的平行線,必平行于畫面;這第三條線在畫面的透視投影的滅點必然在另一條透視投影線上。

             

             

             

            二、透視投影變換學習總結

            1、用多維數列表示低維空間坐標,加深理解齊次坐標表示法。

                齊次坐標表示法可以方便地運算,同時形狀不變。[x,y,z,0]表示一個無窮的點。

               

            2、透視投影變換公式可以看成兩個矩陣的乘積,其中一個做透視變換,另外一個作正投影

               保留的z'值的確切含義:指的是在完全作完透視投影變換之前,僅作透視投影之后的一條線.

               它的幾何意義見李建平《計算機圖形學原理教程》第44頁。

            3、左手和右手坐標系的坐標轉換

               “視點坐標系與一般的物體所在的世界坐標系不同,它遵循左手法則,即左手大拇指指向Z正軸,與之垂直的四個手指指向X正軸,四指彎曲90度的方向是Y正軸。而世界坐標系遵循右手法則的。”

            4、視點坐標系的透視變換公式很重要!!王飛著計算機圖形學書65

            5z'值的確切含義:指的是在完全作完透視投影變換之前,僅作透視投影之后的一條線

             

             

             

            三、兩點透視的變換矩陣:

            王飛編著《計算機圖形學基礎》的道理是:

            從平面圖形的平移、旋轉、錯切開始推導,兩點透視的變換矩陣可以看成是:

            物體本身有一個物體坐標系——xw,yw,zw,視點作為原點又構成一個視點坐標系——xeyeze,物體坐標系z軸朝上,y軸朝向遠處;而視點坐標系y軸朝上,z軸朝向遠處。

            這樣,最終的二點透視狀態可以這樣取得,首先把物體的位置的物體坐標系表示法轉化為視點坐標系的表示法(第一個矩陣),然后圍繞視點坐標系的y軸旋轉(第二個矩陣),然后在xyz方向上平移(第三個矩陣),最后做透視變換(第四個矩陣),它的原文是把平移放在第二步,我在平移之前轉動,目的是保證了物體旋轉的軸在離它不遠的地方:

            我使用的矩陣變換如下,原文是是把平移放在第二步:

            [xw,yw,zw,1]* ***

             

            最后所得結果是一個新的矩陣,

            [xe ye ze 1]=[cos*xw-sin*yw+l   zw+m   2sin*xw+2cos*yw+2n-d   (sin*xw+cos*yw+n/d]

            把最后一項變成1,可得

            =[(cos*xw-sin*yw+l)*d/(sin*xw+cos*yw+n   (zw+m)*d/(sin*xw+cos*yw+n)   2sin*xw+2cos*yw+2n-d*d/(sin*xw+cos*yw+n)    1 ]


            即:

            Xe= (cos*xw-sin*yw+l)*d/(sin*xw+cos*yw+n)

            Ye=(zw+m)*d/(sin*xw+cos*yw+n)

            Ze=(2sin*xw+2cos*yw+2*n-d)*d/(sin*xw+cos*yw+n)

             

            實際上我的delphi程序里面是這樣的:

            xe:=trunc((cos(angle)*eee[ii][k].X-sin(angle)*eee[ii][k].Y+l)*d/(sin(angle)*eee[ii][k].X+cos(angle)*eee[ii][k].Y+n));

                    ye:=trunc((hhh[ii][k]+m)*d/(sin(angle)*eee[ii][k].X+cos(angle)*eee[ii][k].Y+n)); //透視變換

                    //ze可以考慮使用作為消隱

            Ze:=trunc((2*sin(angle)*xw+2*cos(angle)*yw+2*n-d)*d/(sin(angle)*xw+cos(angle)*yw+n));

             

             

            四、通過變換過的兩點透視的結果xe,yezw*,反求原來的物體坐標xw,yw

            即:xe,yezw已知,求出xw,yw

            根據:

            Xe= (cos*xw-sin*yw+l)*d/(sin*xw+cos*yw+n)          1

            Ye=(zw+m)*d/(sin*xw+cos*yw+n)                         2

            Ze=2sin*xw+2cos*yw+2n-d*d/(sin*xw+cos*yw+n) 3

            1)除以(2)得

            Xe/Ye= (cos*xw-sin*yw+l)/ (zw+m)

            (Xe*(zw+m))/Ye=cos*xw-sin*yw+l

            (Xe*(zw+m))/(Ye* cos)=xw-tan*yw+l/cos

            Xw=(Xe*(zw+m))/ (Ye* cos) - (ye*l)/(Ye* cos)+( sin*yw*ye)/ (Ye* cos)

             

            Xw=(Xe*(zw+m)+ sin*yw*ye- ye*l)/ (Ye* cos)            (4)

             

            由(2)得

            Ye*(sin*xw+cos*yw+n)= (zw+m)*d

            Ye*(sin*xw)+ye* cos*yw+n*ye=(zw+m)*d

            把(4)代入上式得

            Ye* sin*(Xe*(zw+m)+ sin*yw*ye- ye*l)/ (Ye* cos)+ye* cos*yw+n*ye=(zw+m)*d

            約去ye,得

            sin*(Xe*(zw+m)+ sin*yw*ye- ye*l)/ cos+ye* cos*yw+n*ye=(zw+m)*d

            tan*(Xe*zw+xe*m+ sin*yw*ye- ye*l) +ye* cos*yw+n*ye=(zw+m)*d

            tan*Xe*zw+xe*m *tan- ye*l*tan+ sin*tan*yw*ye+ye* cos*yw+n*ye=(zw+m)*d

            (sin*tan*ye+ye* cos)*yw+ tan*Xe*zw+xe*m *tan- ye*l*tan+n*ye=(zw+m)*d

             

            最后得

            Yw=[(zw+m)*d- tan*Xe*zw- xe*m *tan+ ye*l*tan- n*ye]/ (sin*tan*ye+ye* cos) 5

            而前面已經得到

            Xw=(Xe*(zw+m)+ sin*yw*ye- ye*l)/ (Ye* cos)            (4)

             

            實際上相當于opengl里面的逆變換,從鼠標選中的屏幕位置來確定對應的三維空間中位置,opengl使用gluUnProjectgluUnProject4來計算。

            posted @ 2010-12-06 14:19 wrh 閱讀(1280) | 評論 (0)編輯 收藏
                 摘要: 1. API之網絡函數 WNetAddConnection 創建同一個網絡資源的永久性連接 WNetAddConnection2 創建同一個網絡資源的連接 WNetAddConnection3 創建同一個網絡資源的連接 WNetCancelConnection 結束一個網絡連接 WNetCancelConnection2 結束一個網絡連接 WNetCloseEnum 結束一次枚舉操作 ...  閱讀全文
            posted @ 2010-12-02 09:20 wrh 閱讀(1923) | 評論 (0)編輯 收藏
                 摘要: //本機網絡連接類型(成功)   #define  NET_TYPE_RAS_DIAL_UP_CONNECT_NET           0x01    //上網類型:采用RAS撥號連接上網 ...  閱讀全文
            posted @ 2010-12-02 09:07 wrh 閱讀(9491) | 評論 (0)編輯 收藏
            和所有初學者一樣,剛開始接觸新的東西,總想把畫面做的漂亮些,可是在vc中很難做到,比如對話框中按鈕等控件的字體設置,就頗費了我一番功夫。
                一。做成一個函數,改變字體大小,方法如下:
                  1。在最開頭聲明一個全局的字體指針 CFont *my_font=new CFont();//注意初始化,不能為空
                  2。在需要改變字體的地方調用函數:
                      set_font(60,my_font,"隸書"); //字體大小、指針、名稱
                      GetDlgItem(IDC_anniu)->SetFont(my_font);//改變字體
                  3。對與不同的字體,你需要設置不同的字體指針就可以了。
                  4。注意在退出時要刪除字體,否則多次調用出現問題
                   BOOL CMyDlg::DestroyWindow()
                  {
                   if (my_font)   my_font->DeleteObject();
                   return CDialog::DestroyWindow();
                  }
                  5。 以下是函設置字體函數的詳細內容:
            void set_font(int height,CFont *font,char *name)
            {
            // font=new CFont();//不在此,要在外部初始化,否則找不到指針
                 LOGFONT lf;
               lf.lfHeight=20;          lf.lfWidth= 0;
            lf.lfEscapement=0;    lf.lfOrientation= 0;
            lf.lfWeight= 760;      lf.lfItalic= 0;
            lf.lfUnderline =0;      lf.lfStrikeOut =0;
            lf.lfCharSet =134; lf.lfOutPrecision =3;
            lf.lfClipPrecision =2; lf.lfQuality= 1;
            lf.lfPitchAndFamily =2; lstrcpy(lf.lfFaceName, "宋體");
            lf.lfOutPrecision =OUT_TT_ONLY_PRECIS;//OUT_TT_PRECIS;
               
            lf.lfHeight= height;   //字體大小
                 lstrcpy(lf.lfFaceName, name);//名稱
                if (font!=NULL)
                {
            font->DeleteObject();
            font->CreateFontIndirect(&lf);
                }
            }
              
            #define say(ch) AfxMessageBox(ch)//自己使用的提示函數
            #define bt(ch)   SetWindowText(ch)//自己使用的提示函數
              
            二。改變字體顏色,要加入系統函數
            HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
            {
            HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
            //    return hbr;
                switch(nCtlColor)
            {
            case CTLCOLOR_STATIC://靜態文本
               TCHAR lpszClassName[255];
               GetClassName(pWnd->m_hWnd, lpszClassName, 255);
               if(_tcscmp(lpszClassName, TRACKBAR_CLASS) == 0)//類名是拉動條
                return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
               else if (IDC_tishi==pWnd->GetDlgCtrlID())//指定的控件ID提示
                {
                 pDC ->SetTextColor(RGB(255,100,100));//RGB(100,255,100)
                 return hbr;
                }
               else
                {
                 pWnd->GetWindowText(ch,40);
                 if (   strcmp(ch,"測試數據")==0 )//指定的標題
                 {
                  pDC ->SetTextColor(RGB(255,0,200));
                     return hbr;  
                 }
                 pDC->SetBkColor(RGB(255,255,255));
                 return hbr;//(HBRUSH) GetStockObject(HOLLOW_BRUSH);
                }
               }
               break;
                 case CTLCOLOR_BTN://按鈕,好象不行
               // pDC ->SetBkMode(OPAQUE);//背景不透明
                // pDC->SetBkMode(TRANSPARENT);//背景透明
            //   say("button");
                    CString str;
            //owen draw //注意,右擊按鈕屬性改為自繪式
                 pWnd->GetWindowText(str); //得到標題內容
                 RECT rect;
                  pWnd->GetClientRect(&rect);//得到矩形范圍大小
               pDC->SelectStockObject(BLACK_PEN);
               pDC->Rectangle(&rect);//黑筆畫外邊矩形
               rect.left+=2;rect.top+=2;
               rect.right-=2 ;rect.bottom-=2;
               pDC->SelectStockObject(WHITE_PEN);
               pDC->Rectangle(&rect);//白筆畫內矩形
               pDC->SelectObject(font);//選擇字體,大小
               pDC->SetTextColor(RGB(0,255,0)); //字體得前景顏色
               pDC->SetBkColor(RGB(255,0,255)); //字體的背景顏色
               pDC->DrawText(str, &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
               return (HBRUSH) GetStockObject(HOLLOW_BRUSH);
                    break;
                 case CTLCOLOR_EDIT://
            編輯框
                    pDC ->SetTextColor(RGB(255,0,0));//文本顏色
                    pDC ->SetBkColor(RGB(255,255,255));//文本背景
                    break;
                 case CTLCOLOR_LISTBOX://
            列表框
                // pDC ->SetTextColor(RGB(255,255,0));
                // pDC ->SetBkColor(RGB(160,60,0));
                    break;
                 }
            // TODO: Return a different brush if the default is not desired
            return hbr;
            }
            posted @ 2010-12-02 08:54 wrh 閱讀(2722) | 評論 (0)編輯 收藏

            2008-06-23 星期一 天氣  

                  很久沒有來這里寫東西了,感覺真有點對不起這個空間. 
             過年到現在一直都忙于工作.(項目一個接一個.報告一個接一個) 
            驅動開發我關注很久了.就是沒有實際行動.終于有一天不知道怎么了下定了決心搞了. 
            首先要搞的是編譯和編輯環境,個人感覺網上有很多DDK Visual Studio6的配置很多都是有問題的,而且都是幾年前寫的.不知道是我理解能力有問題還是作者表達能力有問題老是弄不好.最后弄雖然弄好也是轉了一個大圈.但是用起來實在是不敢恭謹.也許是我用慣了delphi vs2005的緣故.vs2005的代碼編輯和智能排版功能可以說是very Good ! 最后我還是決定把ddkvs2005給掛上關系.花了我一個上午的時間也弄出來了.用起來比vs6.0爽了很多.效果也達到了之前設想的.我寫這些出來是為了減少步我后塵的同志們對驅動的恐懼.

            步驟:
            1.首先前期準備: 安裝xp ddk  vs2005 (vs2005只要安裝c/c++就可以了) 安裝的步驟我就不在這里說了.

            2.準備一個驅動源代碼(ddk內的例子也可以)

            3.vs2005建立一個makeFile 工程.

            4.把源碼拷貝倒vs2005目錄內(包括*.c , *.h,還有source  makefile)

            5.vs2005工程目錄建立一個MakeDriver.bat 文件里面內容是:

            @echo off

            if "%1"=="" goto usage1
            if "%3"=="" goto usage2
            if not exist %1\bin\setenv.bat goto usage3

            echo params1: %1 
            echo params2: %2
            echo params3: %3


            echo call %1\BIN\setenv %1 %3
            call %1\BIN\setenv %1 %3

            echo cd /d %2
            cd /d %2


            build
            goto ok

            :usage1
            echo Error: the first parameter is NULL!
            goto exit

            :usage2
            echo Error: the third parameter is NULL!
            goto exit

            :usage3
            echo Error: %1\bin\setenv.bat not exist!
            goto exit

            :ok
            echo MakeDriver %1 %2 %3
            :exit

            5. 設置 vs2005 工程的屬性
                編譯分 debug release 兩個版本

            NMke 設置里面設置 ( 我用的是 vs2005 繁體版






























            releasee 版本.只要將 建置命令列 內容改成 MakeDriver %DDKROOT% $(ProjectDir) fre 就可以了.


            我的 ddk 是安裝在 c .IntelliSense 是為了能在編輯代碼的時候彈出輸入的列表 . 比如結構體內的成員等等


            建置命令列 : 是調用 MakeDriver.bat 文件編譯源代碼 .


            如果加上 vss 代碼管理 . 一個驅動代碼工程管理就算完善了 .

            寫到這里了 .

            順便提下要了解 MakeDriver.bak 內的作用就要了解一些批處理的 dos 命令 . 上網找吧 . 網上什么都有關鍵是看你怎么找 .

            posted @ 2010-12-01 13:12 wrh 閱讀(794) | 評論 (0)編輯 收藏

             http://harborwan.blog.sohu.com/39762230.html

            通常驅動程序的調試都是用ddk在cmd中完成的。這部分我暫時略過。下面先介紹如何設置vc++6.0在Visual Studio 6.0集成環境中開發設備驅動程序的方法。

            在Windows上,Windows DDK提供的開發環境是基于命令行的,操作起來極為不便,而Visual Studio 6.0給我們提供了非常友好易用的集成環境,讓我們有如虎添翼之感。 
              那么,能否利用Visual Studio的集成環境來開發驅動程序呢?答案是可以的。通過對Visual Studio集成環境的簡單設置,創建好自己的驅動開發集成環境就可以了。

            1,

            第一:安裝Vc++6.0,我裝的是英文版,中文版應該也可以,不過我沒試。

            第二:安裝winXP DDK,注意,安裝目錄中間不能有空格,比如D:\Program Files不行,

            我直接裝在了D盤,裝完后設置環境變量DDKROOT為安裝目錄D:\WINDDK\2505。

            2,創建一個目錄,作為開發目錄,我是利用<<PCI設備開發寶典>>的光盤中的工程文件PCI9052Demo,直接考到E盤,所以,工作目錄下是E:\PCI9052Demo

            3,工作目錄下創建一個批處理文件MakeDrvr.bat,內容如下:

            @echo off
            if "%1"=="" goto usage
            if "%3"=="" goto usage
            if not exist %1\bin\setenv.bat goto usage
            call %1\bin\setenv %1 %4
            %2
            cd %3
            build -b -w %5 %6 %7 %8 %9
            goto exit

            :usage
            echo usage   MakeDrvr DDK_dir Driver_Drive Driver_Dir free/checked [build_options]
            echo eg      MakeDrvr %%DDKROOT%% F: %%WDMWorkshop%% free -cef
            :exit

            解釋以下:

            1% 是DDK_dir,也就是ddk的安裝目錄

            2% 是Driver_Drive,是你工作目錄所在的盤符,這里是E:

            3% 是Driver_Dir,是你工作目錄的路徑,這里是E:\PCI9052Demo

            4% 是編譯模式,checked表示調試模式,free表示發行模式,這里是出問題的地方,后面再說。

            該批處理首先對傳遞的參數作一些檢查,然后調用ddk的setenv命令設置環境變量,然后改變目錄為源程序所在驅動器和目錄,并最后調用build,-b保證顯示完全的錯誤信息,-w保證在屏幕上輸出警告,在vc ide里的output窗口中可以看到這些錯誤和警告。

            4,建立一個空白工程
             選File的new菜單項,然后選project欄的makefile,然后輸入路徑,一路next下去即可,visual studio提供兩種配置win32 debug和win32 release. 按照cant的《windows wdm 設備驅動程序開發指南》方法,可以刪除掉,添加Win32 Checked和 Win32 Free

            5,VC的Project->settings里面改變設置

            修改這兩種配置
             =============================================================
             Free
             =============================================================
             build command line:
             e:\PCI9052Demo\MakeDrvr %DDKROOT% e: e:\PCI9052Demo free
             
             rebuild all opinions:
             -nmake /a

             output filename:
             PCI9052Demo.sys

             browse info file name:
             objfre\i386\PCI9052Demo.bsc


             =============================================================
             Checked
             =============================================================
             build command line:
             e:\PCI9052Demo\MakeDrvr %DDKROOT% e: e:\PCI9052Demo checked
             
             rebuild all opinions:
             -nmake /a

             output filename:
             PCI9052Demo.sys

             browse info file name:
             objfre\i386\PCI9052Demo.bsc

            6.添加源文件到工程
              可以新建,也可

            posted @ 2010-12-01 13:11 wrh 閱讀(272) | 評論 (0)編輯 收藏
            僅列出標題
            共25頁: 1 2 3 4 5 6 7 8 9 Last 

            導航

            <2011年3月>
            272812345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            統計

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            午夜精品久久久久久久久| 久久亚洲国产午夜精品理论片| 久久男人中文字幕资源站| 久久精品?ⅴ无码中文字幕| 伊人伊成久久人综合网777| 中文字幕乱码人妻无码久久| 久久99国产精品尤物| 青春久久| 99久久精品免费观看国产| 亚洲欧美成人久久综合中文网 | 久久精品成人免费观看97| 久久精品无码一区二区WWW| 人人狠狠综合久久亚洲婷婷| 久久强奷乱码老熟女网站| 精品久久久久久国产三级 | 欧美日韩精品久久久免费观看| www.久久热| 久久99精品国产自在现线小黄鸭| 亚洲婷婷国产精品电影人久久| 久久成人影院精品777| 99久久香蕉国产线看观香| 国产精品久久久久乳精品爆| 久久久久久人妻无码| 久久精品亚洲AV久久久无码| 亚洲精品99久久久久中文字幕| 国产精品免费久久久久久久久| 香蕉久久夜色精品国产尤物| 色8久久人人97超碰香蕉987| 久久精品成人欧美大片| 996久久国产精品线观看| 色偷偷偷久久伊人大杳蕉| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 精品久久久久久国产牛牛app| 97精品国产91久久久久久| 久久棈精品久久久久久噜噜| 精品无码久久久久国产动漫3d| 亚洲国产天堂久久久久久| 久久综合给合综合久久| 日日狠狠久久偷偷色综合96蜜桃 | 青春久久| 99久久免费国产精品特黄|