最近项目中的Win32开发技巧拾遗

来源:互联网 发布:外国人的懒惰程度知乎 编辑:程序博客网 时间:2024/05/16 10:23

1.       WinSock的初始化和关闭的智能管理。

使用全局static对象,可实现在模块被调用时初始化WinSock,在模块卸载时关闭WinSock

#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")

 

class CWinSockGuard

{

public:

    CWinSockGuard()

    {

       m_bInitOK = false;

       WORD wVersionRequested = MAKEWORD(1, 1);

       WSADATA wsaData;

       int nReturnCode = WSAStartup(wVersionRequested, &wsaData);

       switch(nReturnCode)

       {

       case 0:                  //OK  

           {

              m_bInitOK = true;

              break;

           }

       case WSASYSNOTREADY: //the underlying network subsystem is not ready for network communication

       case WSAVERNOTSUPPORTED://The version of Windows Sockets support requested is not provided.

       case WSAEFAULT:          //The lpWSAData parameter is not a valid pointer.

           {

              m_bInitOK = false;

              break;

           }

       }

    }

    ~CWinSockGuard()

    {

       if(m_bInitOK)

       {

           WSACleanup();

       }

    }

private:

    bool m_bInitOK;

};

//Just make sure we Init and Cleanup WinSock module properly

static CWinSockGuard g_cWinSockGuard; 

 

2.       WinSockUDPrecvfrom函数返回值处理。

           if(nRecvLength == SOCKET_ERROR)

           {

              //返回-1一般是出错的情况,可调用WSAGetLastError获得错误码,一般情形下可忽略该问题,继续接收数据。

              //If an error occurs,a value of SOCKET_ERROR is returned,

              //and a specific error code can be retrieved by calling WSAGetLastError.

              int nErrorCode = WSAGetLastError();

             

              //UDP中返回10054的问题:一般是在当调用sendto发送到一个UDP端口未开启的对端时,selecet显示有数据可断,调用recvfrom返回-1,错误码为:10054,该问题可忽略,继续接收数据即可。

              //If a SendData request is sent to a RemoteHost that is not listening on the RemotePort,

              //the DataArrival event fires and indicates that 1 byte of data is available.

              //When you call the GetData method to retrieve that data, the following run-time error occurs:

              //'10054' - "The connection is reset by remote side".

              continue;

           }

           else if(nRecvLength == 0)

           {

              //返回0,一般是本地套接字已关闭(本线程或其它线程可能调用了closesocket),此时不应再接收数据

              //If the connection has been gracefully closed, the return value is zero.

              break;

           }

 

3.       64位整型数据的处理问题。

数据的打印,在WIN32中,一般使用:%I64d%I64u,分别对应__int64unsigned __int64。而在GCC中,一般使用:%lld%llu,分别对应unsigned long longlong long

数据的随机生成方法:

(UINT64)((UINT64)rand() ^  ((UINT64)rand() << 15) ^  ((UINT64)rand() << 30) ^ ((UINT64)rand() << 45) ^  ((UINT64)rand() << 60))

 

4.       使用Dependency Walker查看VS2005编译出来的dll中,发现依赖msvcp80.dllmsvcr80.dll出现问号的问题!

建立一个dll工程,默认“使用标准 Windows 库”,编译出来的dll文件用dependency打开,发现包含一个MSCVR80.dll,并且前面打着问号。使用这个dll的程序在未安装vc的电脑上不能运行。解决方法:在工程设置里选择“在静态库中使用 MFC”,保存。然后再选择回“使用标准 Windows 库”,保存。重新编译dll。用dependency查看可以发现MSCVR80.dll已经没有了。

http://blog.csdn.net/sunrisemaple/archive/2008/04/27/2334573.aspx

 

5.       Windows消息队列函数重温

备注:Windows消息队列函数以下函数的特点耐人寻味(GetMessage, PeekMessage, PostMessage, PostThreadMessage, SendMesage)

其中PeekMessage的调用是立即返回的,并不等待消息队列中有消息才返回,并且对于WM_QUIT消息的处理与GetMessage也是不同的,值得关注。

 

GetMessage

This function retrieves a message from the calling thread's message queue and places it in the specified structure.

Return Values

Nonzero indicates that the function retrieves a message other than WM_QUIT. Zero indicates that the function retrieves the WM_QUIT message, or that lpMsg is an invalid pointer. To get extended error information, call GetLastError.

 

PeekMessage

This function checks a thread message queue for a message and places the message (if any) in the specified structure.

wRemoveMsg

[in] Specifies how messages are handled. This parameter can be one of the following values.

Value

Description

PM_NOREMOVE

Messages are not removed from the queue after processing by PeekMessage.

PM_REMOVE

Messages are removed from the queue after processing by PeekMessage. An exception is WM_PAINT messages, which are not removed from the queue.

You can optionally combine the value PM_NOYIELD with either PM_NOREMOVE or PM_REMOVE. This flag prevents the system from releasing any thread that is waiting for the caller to go idle.

Return Values

Nonzero indicates success. Zero indicates failure.

Unlike the GetMessage function, the PeekMessage function does not wait for a message to be placed in the queue before returning.

 

PostMessage

This function places a message in the message queue associated with the thread that created the specified window and then returns without waiting for the thread to process the message.

PostThreadMessage

This function places a message in the message queue of the specified thread and then returns without waiting for the thread to process the message.

SendMessage

This function sends the specified message to a window or windows.