jackba / wy-internal-system

Automatically exported from code.google.com/p/wy-internal-system
0 stars 0 forks source link

MFC CButton #2

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
DrawItem()

Original issue reported on code.google.com by Giggs...@gmail.com on 17 Feb 2012 at 7:40

GoogleCodeExporter commented 9 years ago
//Draw Icon/Text,Owner Draw
void ButtonRno::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{

    CDC *pCDC = CDC::FromHandle(lpDrawItemStruct->hDC); 

    pCDC->SetBkMode(TRANSPARENT);

    CRect itemRect = lpDrawItemStruct->rcItem;

    HICON hIcon = AfxGetApp() -> LoadIcon(IDI_ICON2);
    pCDC->DrawState(itemRect.TopLeft(), itemRect.Size(), hIcon, DSS_NORMAL, (CBrush*)NULL);

    pCDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
    pCDC->DrawText(L"Rooney", -1, itemRect, DT_CENTER);
}

Original comment by Giggs...@gmail.com on 17 Feb 2012 at 7:41

GoogleCodeExporter commented 9 years ago
MouseOn/MouseMove:

BEGIN_MESSAGE_MAP(ButtonRno, CButton)
    ON_WM_MOUSEMOVE()
    ON_WM_SETFOCUS()
    ON_WM_KILLFOCUS()
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
END_MESSAGE_MAP()

    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    afx_msg void OnMouseMove(UINT nHitTest, CPoint point);
    afx_msg void OnKillFocus(CWnd* cwnd);
    afx_msg void OnSetFocus(CWnd* cwnd);
    LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
    LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);

LRESULT ButtonRno::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{   CDC *pCDC = this->GetDC();

    pCDC->SetBkMode(TRANSPARENT);

    CRect itemRect;
    this->GetClientRect(&itemRect);

    HICON hIcon = AfxGetApp() -> LoadIcon(IDI_ICON2);
    pCDC->DrawState(itemRect.TopLeft(), itemRect.Size(), hIcon, DSS_NORMAL, (CBrush*)NULL);

    pCDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
    pCDC->DrawText(L"Rooney", -1, itemRect, DT_CENTER);
    return S_OK;
}
LRESULT ButtonRno::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
        CDC *pCDC = this->GetDC();

    pCDC->SetBkMode(TRANSPARENT);

    CRect itemRect;
    this->GetClientRect(&itemRect);

    HICON hIcon = AfxGetApp() -> LoadIcon(IDI_ICON_MU);
    pCDC->DrawState(itemRect.TopLeft(), itemRect.Size(), hIcon, DSS_NORMAL, (CBrush*)NULL);

    pCDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
    pCDC->DrawText(L"focused", -1, itemRect, DT_CENTER);

    return S_OK;
}
void ButtonRno::OnMouseMove(UINT nHitTest, CPoint point)
{  
    TRACKMOUSEEVENT   tme; 
    tme.cbSize=sizeof(TRACKMOUSEEVENT); 
    tme.dwFlags=TME_HOVER   |   TME_LEAVE; 
    tme.dwHoverTime=HOVER_DEFAULT; 
    tme.hwndTrack=m_hWnd; 
    if(!_TrackMouseEvent(&tme)) 
    {
            AfxMessageBox( L"鼠标事件捕捉失败! ");
    }
}

Original comment by Giggs...@gmail.com on 22 Feb 2012 at 9:31

GoogleCodeExporter commented 9 years ago
#pragma  once

#include "../../Core/Protocol/Handler.h"
#include "../../Core/Protocol/Inc/Header.h"
#include "../../Core/Common/WCLaoType.h"

void Protocol_Init(int &iHeaderSize, int &iBodyOffset, CB_MidCallback cb);
void Protocol_Dispatcher(enumNetworkOperationType t, char *pszData, size_t 
stLength, bool &bServerDisconnect);

#include "stdafx.h"
#include "Handler.h"
#include "Inc/Header.h"
#include "../../Core/Debug/Debug.h"
#include "../../Core/Network/Net.h"
#include "../../Core/Common/UserInfo.h"
#include "../../Core/Console/Console.h"

static CB_MidCallback m_cb = NULL;

void Protocol_Init(int &iHeaderSize, int &iBodyOffset, CB_MidCallback cb)
{
    Protocol_InfoGetSet(iHeaderSize, iBodyOffset);
    m_cb = cb;
}
void Protocol_Dispatcher(enumNetworkOperationType t, char *pszData, size_t 
stLength, bool &bServerDisconnect)
{
    switch (t)
    {
    case C_LOGIN:
        break;
    case S_RESPONSE_LOGIN:
            PrintConsoleLog(WCLao_DEBUG, "login success...");
            UserInfo_SetLoginStatus(true);//loging success
            m_cb(S_RESPONSE_LOGIN, NULL, 0);
        break;
    case S_FRIEND_LIST:
        break;
    case C_OPRSP_1:
            PrintConsoleLog(WCLao_DEBUG, "C_OPRSP_1...X");
        break;
    case C_OPRSP_2:
            PrintConsoleLog(WCLao_DEBUG, "C_OPRSP_2...X");
        break;
    case C_OPRSP_3:
            PrintConsoleLog(WCLao_DEBUG, "C_OPRSP_3...X");
        break;

    default:
        //OutputDebugInfoA("UNKOWN NETWORK OPERATION TYPE!", __FILE__, __FUNCTION__):
        break;
    }
    if (bServerDisconnect)
    {
        m_cb(DROPLINE, NULL, 0);
    }

} 

Original comment by Giggs...@gmail.com on 29 Jul 2013 at 2:19

GoogleCodeExporter commented 9 years ago
#pragma once

#include "../../Core/Common/WCLaoType.h"
#include "../../Core/Network/Net.h"

//interface
//
bool MID_Login(char *pszServerIP, int iServerPort, int iUserID, char 
*pwszPassword);//connect to server & login
bool MID_OP_1();
bool MID_OP_2();
bool MID_OP_3();
bool MID_Logout();
void MID_breath();
//assist func
//
void MID_Init(HWND h, CB_MidCallback cb, int iProtocolHeaderSize, int 
iProtocolBodyLen);
void MID_Fini();
bool MID_StartCommunication(char *pszServerIP, int iServerPort);
void MID_StopCommunication();

#include "stdafx.h"
#include "Communication.h"
#include "../../Core/Network/Net.h"
#include "../../Core/Console/Console.h"
#include "../../Core/Debug/Debug.h"
#include "../../Core/Protocol/Inc/DataPacker.h"
#include "../../Core/Protocol/Handler.h"
#include "../../Core/Common/UserInfo.h"

static CB_MidCallback m_cb = NULL;

static void NetworkPackageHandler(char *data, int len)
{
    if (!data)
    {   
        m_cb(DROPLINE, NULL, 0);
        return;
    }
    CommonHeader *p = (CommonHeader *)data;
    bool bServerDisconnect = false;
    Protocol_Dispatcher(p->enot, data, len, bServerDisconnect);
    delete data;
}
void MID_Init(HWND h, CB_MidCallback cb, int iProtocolHeaderSize, int 
iProtocolBodyLen)
{
    m_cb = cb;
    NW_Init(h, iProtocolHeaderSize, iProtocolBodyLen, (CB_NetworkPackageCallback)NetworkPackageHandler);
}
void MID_Fini()
{
    NW_Fini();
}
bool MID_OP_1()
{
    char *pszDataSend = NULL;
    unsigned int dwLength = 0;
    if (!Protocol_H_GetRequestData_OP1(pszDataSend, dwLength))
    {
        return false;
    }
    if (!NW_PostSend(pszDataSend, dwLength))
    {
        return false;
    }
    PrintConsoleLog(WCLao_INFO, "OP_1 sent");
    return true;
}
bool MID_OP_2()
{
    char *pszDataSend = NULL;
    unsigned int dwLength = 0;
    if (!Protocol_H_GetRequestData_OP2(pszDataSend, dwLength))
    {
        return false;
    }
    if (!NW_PostSend(pszDataSend, dwLength))
    {
        return false;
    }
    PrintConsoleLog(WCLao_INFO, "OP_2 sent");
    return true;
}
bool MID_OP_3()
{
    char *pszDataSend = NULL;
    unsigned int dwLength = 0;
    if (!Protocol_H_GetRequestData_OP3(pszDataSend, dwLength))
    {
        return false;
    }
    if (!NW_PostSend(pszDataSend, dwLength))
    {
        return false;
    }
    PrintConsoleLog(WCLao_INFO, "OP_3 sent");
    return true;
}
bool MID_Login(char *pszServerIP, int iServerPort, int iUserID, char 
*pszPassword)
{
    //connect to server first
    if (!MID_StartCommunication(pszServerIP, iServerPort))
    {
        return false;
    }
    //send user name & password then
    char *pszDataSend = NULL;
    DWORD dwLength = 0;
    if (!Protocol_H_GetLoginRequestData(pszDataSend, dwLength, iUserID, pszPassword))
    {
        return false;
    }
    UserInfo_SetUserID((((struct_Login_Req_C *)(pszDataSend + SIZE_CommonHeader))->iUserID));//set user ID
    if (!NW_PostSend(pszDataSend, dwLength))
    {
        return false;
    }
    PrintConsoleLog(WCLao_INFO, "login req sent");
    do
    {
        static int time = 0;
        if (UserInfo_GetLoginStatus())
        {
            break;
        }
        else
        {
            Sleep(1000);
            time++;
            if (time == 10)
            {
                PrintConsoleLog(WCLao_INFO, "login time out!");
                return false;//time out error
            }
        }
    }
    while (true);
    return true;
}
bool MID_Logout()
{
    DWORD dwBytesSentCount = SIZE_CommonHeader;
    char *pszDataSend = Protocol_H_GetLogoutRequestData();
    if (!NW_PostSend(pszDataSend, dwBytesSentCount))
    {
        return false;
    }
    PrintConsoleLog(WCLao_INFO, "logout req sent");

    return true;
}
bool MID_StartCommunication(char *pszServerIP, int iServerPort)
{
    return NW_PostConnect(pszServerIP, iServerPort);
}
void MID_StopCommunication()
{
    NW_DisconnectToServer();
}
void MID_breath()
{
    char *pszDataSend = Protocol_H_GetBreathRequestData();
    if (!NW_PostSend(pszDataSend, SIZE_CommonHeader))
    {
        PrintConsoleLog(WCLao_ERROR, "breath sent error!");
    }
    else
    {
//      PrintConsoleLog(WCLao_ERROR, "breath sent OK!");
    }
}
bool UserInfo_GetServerAnnouncement()
{
    return true;
}

Original comment by Giggs...@gmail.com on 29 Jul 2013 at 2:20

GoogleCodeExporter commented 9 years ago
// MainBoardDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "WCLao.h"
#include "WCLaoDlg.h"
#include "MainBoardDlg.h"
#include "WCLaoMessage.h"
#include "Core/UI/Communication.h"
#include "Core/Debug/Debug.h"
#include "PrivateChatDlg.h"
#include "Core/Console/Console.h"

static CString g_sFriendKeyTemp;
CMainBoardDlg *g_p = NULL;

static void OnDropline(enumNetworkOperationType t, char *pszData, size_t 
stLength)
{
    KillTimer(g_p->GetSafeHwnd(), 0);
}
// CMainBoardDlg 对话框

IMPLEMENT_DYNAMIC(CMainBoardDlg, CDialog)

CMainBoardDlg::CMainBoardDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CMainBoardDlg::IDD, pParent)
{
    UserInfo_Init();
}

CMainBoardDlg::~CMainBoardDlg()
{
    UserInfo_Fini();
    Shell_NotifyIcon(NIM_DELETE, &m_nidNotifyIcon);
}

void CMainBoardDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STATIC_USER_NAME, m_staticUserName);
    DDX_Control(pDX, IDC_STATIC_STATUS, m_staticUserStatus);
    DDX_Control(pDX, IDC_TREE_FRIEND_LIST, m_tvFriendList);
    DDX_Control(pDX, IDC_EDIT_Message, m_editMessage);
}

BEGIN_MESSAGE_MAP(CMainBoardDlg, CDialog)
    ON_MESSAGE(WM_SWITCH_TO_MAINBOARD_WND, &CMainBoardDlg::OnSwitchToMainBoardWnd)
    ON_WM_CLOSE()
    ON_WM_TIMER()
    ON_NOTIFY(NM_DBLCLK, IDC_TREE_FRIEND_LIST, &CMainBoardDlg::OnNMDblclkTreeFriendList)
    ON_NOTIFY(NM_RCLICK, IDC_TREE_FRIEND_LIST, &CMainBoardDlg::OnNMRClickTreeFriendList)
    ON_COMMAND(ID_CHAT, &CMainBoardDlg::OnChat)
    ON_MESSAGE(WM_NOTIFY_ICON, &CMainBoardDlg::OnNotifyIcon)
    ON_BN_CLICKED(IDC_BUTTON_MINIMIZE, &CMainBoardDlg::OnBnClickedButtonMinimize)
    ON_NOTIFY(NM_CLICK, IDC_TREE_FRIEND_LIST, &CMainBoardDlg::OnNMClickTreeFriendList)
    ON_BN_CLICKED(IDC_BUTTON2, &CMainBoardDlg::OnBnClickedButton2)
    ON_BN_CLICKED(IDC_BUTTON3, &CMainBoardDlg::OnBnClickedButton3)
    ON_BN_CLICKED(IDC_BUTTON4, &CMainBoardDlg::OnBnClickedButton4)
    ON_BN_CLICKED(IDC_BUTTON5, &CMainBoardDlg::OnBnClickedButton5)
    ON_BN_CLICKED(IDC_BUTTON6, &CMainBoardDlg::OnBnClickedButton6)
    ON_BN_CLICKED(IDC_BUTTON_SEND, &CMainBoardDlg::OnBnClickedButtonSend)
END_MESSAGE_MAP()

// CMainBoardDlg 消息处理程序

LRESULT CMainBoardDlg::OnSwitchToMainBoardWnd(WPARAM wParam, LPARAM lParam)
{
    //DoModal();
    return 0;
}
BOOL CMainBoardDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    CWCLaoDlg dlg;
    INT_PTR iRet = dlg.DoModal();
    if (iRet != IDOK)
    {
        EndDialog(1);
    }
    else
    {
        m_staticUserName.SetWindowText(UserInfo_GetUserName());
        m_staticUserStatus.SetWindowText(UserInfo_GetUserStatusString(UserInfo_GetUserStatus()));
        SetupFriendList();
        ShowNotifyIcon();
    }
//  UserInfo_SetNetworkCallback(OnDropline);

    return TRUE;
}
void CMainBoardDlg::ShowNotifyIcon()
{
    m_nidNotifyIcon.cbSize = sizeof(NOTIFYICONDATA);
    m_nidNotifyIcon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_nidNotifyIcon.hWnd = m_hWnd;
    lstrcpy(m_nidNotifyIcon.szTip, L"NotifyIcon Test");
    m_nidNotifyIcon.uCallbackMessage = WM_NOTIFY_ICON;
    m_nidNotifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    Shell_NotifyIcon(NIM_ADD, &m_nidNotifyIcon);
}
BOOL CMainBoardDlg::PreTranslateMessage(MSG* pMsg)
{   
    if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN))
    {
        return NULL;
    }
    if (pMsg->message == WM_NCLBUTTONDOWN)
    {
        if (pMsg->hwnd == this->m_hWnd)
        {
        }
        else
        {
//          ShowWindow(SW_SHOW);
        }
    }
    return CDialog::PreTranslateMessage(pMsg);
}
void CMainBoardDlg::OnClose()
{
    KillTimer(TIMER_breath);
    MID_Logout();
    MID_StopCommunication();
    MID_Fini();
    CDialog::OnClose();
}

void CMainBoardDlg::OnNMDblclkTreeFriendList(NMHDR *pNMHDR, LRESULT *pResult)
{
    m_handleTreeItem = m_tvFriendList.GetSelectedItem();
    g_sFriendKeyTemp = m_tvFriendList.GetItemText(m_tvFriendList.GetSelectedItem());

    PrivateChatDlg *pcd = new PrivateChatDlg;
    pcd->SetFriendKey(g_sFriendKeyTemp);
    pcd->Create(IDD_DIALOG_PRIVATE_CHAT, this);
    pcd->ShowWindow(SW_SHOW);

    *pResult = 0;
}

void CMainBoardDlg::OnNMRClickTreeFriendList(NMHDR *pNMHDR, LRESULT *pResult)
{  
//  AfxMessageBox(m_tvFriendList.GetItemText(m_tvFriendList.GetSelectedItem()));
    //show menu
    //
    m_menuFriend.LoadMenu(IDR_MENU_FRIEND);
    CMenu *p = m_menuFriend.GetSubMenu(0);
    CPoint point;
    GetCursorPos(&point);
    p->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_VERTICAL, point.x, point.y, this, TPM_LEFTALIGN);
    m_menuFriend.DestroyMenu();
    g_sFriendKeyTemp = m_tvFriendList.GetItemText(m_tvFriendList.GetSelectedItem());
    *pResult = 0;
}
void CMainBoardDlg::SetupFriendList()
{
    const struct_FriendInfo *p = UserInfo_GetFriendList();
    //struct_FriendNode *m_friends = NULL, *pTemp = NULL;
    //if (p)
    //{
    //  pTemp = new struct_FriendNode;
    //  m_friends = p;
    //}
    while (p)
    {
        CString s(L"");
        s.AppendFormat(L"%d", p->iUserID);
        m_tvFriendList.InsertItem(s);
//      HTREEITEM h = m_tvFriendList.InsertItem(0, s, 0, 0, 0, 0, p->iUserID, NULL, 
NULL);
        //pTemp->h = h;
        //pTemp->iUserID = p->iUserID;
        //pTemp->pNext = NULL;
        //if (p)
        //{
        //  pTemp->pNext = new struct_FriendNode;
        //  pTemp = pTemp->pNext;
        //}

        p = p->pNext;
    }
}
void CMainBoardDlg::OnChat()
{
//  AfxMessageBox(m_tvFriendList.GetItemText(m_handleTreeItem));

    PrivateChatDlg *pcd = new PrivateChatDlg;
    pcd->SetFriendKey(g_sFriendKeyTemp);
    pcd->Create(IDD_DIALOG_PRIVATE_CHAT, this);
    pcd->ShowWindow(SW_SHOW);
}
afx_msg void CMainBoardDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
    if   (nStatus == SC_MINIMIZE)
    {
        //ShowWindow(SW_HIDE);
        //return;
    }
}
void CMainBoardDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if   (nID == SC_MINIMIZE)
    {
        //ShowWindow(SW_HIDE);
        //return;
    }
    CDialog::OnSysCommand(nID, lParam);
}
afx_msg void CMainBoardDlg::OnSizing(UINT nType, int cx, int cy)
{
    CMainBoardDlg::OnSize(nType, cx, cy);

    //if (nType == SIZE_MINIMIZED)
    //{
    //  ShowWindow(SW_HIDE);
    //  return;
    //}
}
LRESULT  CMainBoardDlg::OnNotifyIcon(WPARAM wParam,LPARAM IParam)
{
    if ((IParam == WM_LBUTTONDOWN) || (IParam == WM_RBUTTONDOWN))
    {
        ModifyStyleEx(0,WS_EX_TOPMOST);
        ShowWindow(SW_SHOW);
    }
    return 0;
}
void CMainBoardDlg::OnBnClickedButtonMinimize()
{
    ShowWindow(SW_HIDE);
}

void CMainBoardDlg::OnNMClickTreeFriendList(NMHDR *pNMHDR, LRESULT *pResult)
{
    m_handleTreeItem = m_tvFriendList.GetSelectedItem();
    *pResult = 0;
}

void CMainBoardDlg::OnBnClickedButton2()
{ MID_OP_1();
}
void CMainBoardDlg::OnBnClickedButton3()
{ MID_OP_2();
}
void CMainBoardDlg::OnBnClickedButton4()
{ MID_OP_3();
}
void CMainBoardDlg::OnTimer(UINT nIDEvent)
{
    static int i = 0;
    if (i % 2 == 0)
    {
        MID_OP_1();
    }
    if (i % 3 == 0)
    {
        MID_OP_2();
    }
    if (i % 5 == 0)
    {
        MID_OP_3();
    }
    i++;

    CDialog::OnTimer(nIDEvent);
}

void CMainBoardDlg::OnBnClickedButton5()
{
    SetTimer(0, 4000, NULL);
}

void CMainBoardDlg::OnBnClickedButton6()
{
    KillTimer(0);
}

void CMainBoardDlg::OnBnClickedButtonSend()
{
    wchar_t s[1024] = {0};
    m_editMessage.GetWindowTextW(s, 1024);

}

Original comment by Giggs...@gmail.com on 29 Jul 2013 at 2:21

GoogleCodeExporter commented 9 years ago
// PrivateChatDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "WCLao.h"
#include "PrivateChatDlg.h"

// PrivateChatDlg 对话框

IMPLEMENT_DYNAMIC(PrivateChatDlg, CDialog)

PrivateChatDlg::PrivateChatDlg(CWnd* pParent /*=NULL*/)
    : CDialog(PrivateChatDlg::IDD, pParent)
{
}

PrivateChatDlg::~PrivateChatDlg()
{
}

void PrivateChatDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_CHAT_LOG, m_editChatLog);
    DDX_Control(pDX, IDC_EDIT_TO_SEND, m_editToSend);
    DDX_Control(pDX, IDC_STATIC_FRIEND_NAME, m_staticFriendName);
    DDX_Control(pDX, IDC_STATIC_MY_NAME, m_staticMyName);
    DDX_Control(pDX, IDC_BUTTON_SEND, m_btnSend);
}
BOOL PrivateChatDlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN))
    {
        return NULL;
    }
    return CDialog::PreTranslateMessage(pMsg);
}
void PrivateChatDlg::PostNcDestroy()
{
    delete this;
}

BEGIN_MESSAGE_MAP(PrivateChatDlg, CDialog)
    ON_BN_CLICKED(IDC_BUTTON_SEND, &PrivateChatDlg::OnBnClickedButtonSend)
END_MESSAGE_MAP()

// PrivateChatDlg 消息处理程序

BOOL PrivateChatDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    SetWindowText(m_sFriendKey);

    return TRUE;
}
void PrivateChatDlg::SetFriendKey(CString sFriendKey)
{
    m_sFriendKey = sFriendKey;
}
void PrivateChatDlg::OnBnClickedButtonSend()
{
    //check void
    //send text
    //add test on above edit control
}

Original comment by Giggs...@gmail.com on 29 Jul 2013 at 2:21

GoogleCodeExporter commented 9 years ago
#pragma  once

#include "../../Core/Common/WCLaoType.h"

typedef enum _enumSocketAvailableType
{
    SOCKET_AVAILABLE_TYPE_READ = 0,
    SOCKET_AVAILABLE_TYPE_WRITE,
    SOCKET_AVAILABLE_TYPE_BOTH
}enumSocketAvailableType;
typedef enum _enumSocketAvailableError
{
    SOCKET_AVAILABLE_TYPE_SUCCESS = 0,
    SOCKET_AVAILABLE_TYPE_DROPLINE = -10000,
    SOCKET_AVAILABLE_TYPE_OTHER = -10001,
    SOCKET_AVAILABLE_TYPE_TIMEOUT = -10002
}enumSocketAvailableError;
typedef struct _struct_DataReceived
{
    int offset;
    int size;
    char *pData;
}struct_DataReceived;

//interface
//
bool NW_Init(HWND h, int iProtocolHeaderSize, int iProtocolBodyLen, 
CB_NetworkPackageCallback pCB);
void NW_Fini();
bool NW_PostConnect(char *pszServerIP, int iServerPort);
void NW_DisconnectToServer();
bool NW_PostSend(char *pszBuffer, int iLength);
int NW_SocketAvailable(SOCKET s, enumSocketAvailableType esat, unsigned int 
iTimeoutSecond);

#include "stdafx.h"
#include "Net.h"
#include "../../Core/Debug/Debug.h"
#include "../../Core/Console/Console.h"
#include "../../Core/Common/String.h"
#include <winsock2.h>
#pragma comment(lib, "WS2_32")

#define  TIMEOUT_Receive 500
#define  TIMEOUT_Send 500
#define  TIMEOUT_Connect 500
static SOCKET m_sockClient;
static struct_DataReceived *m_pDataReceived = NULL;
static DWORD WINAPI RecvThreadProc(LPVOID lpParam);
static HANDLE m_hRecvThread;
static CB_NetworkPackageCallback m_pCB = NULL;
static int m_iProtocolHeaderSize = 0;
static int m_iProtocolBodyLen = 0;

static bool StartSocket(BYTE byteMinorVersion, BYTE byteMajorVersion)
{
    WSADATA wsaData;
    WORD dwSockVersion = MAKEWORD(byteMinorVersion, byteMajorVersion);
    if(::WSAStartup(dwSockVersion, &wsaData) != 0)
    {
        return false;
    }
    return true;
}
static void StopSocket()
{
    ::WSACleanup();
}
//pCB returns a package to upper layer
bool NW_Init(HWND h, int iProtocolHeaderSize, int iProtocolBodyLen, 
CB_NetworkPackageCallback pCB)
{
    m_iProtocolHeaderSize = iProtocolHeaderSize;
    m_iProtocolBodyLen = iProtocolBodyLen;
    m_pCB = pCB;
    //start socket
    if (!StartSocket(2, 2))
    {
        OutputDebugInfoW(L"加載Socket Dll 失敗!", __FILE__, __FUNCTION__);
        return false;
    }

    m_pDataReceived = new struct_DataReceived;
    memset(m_pDataReceived, 0, sizeof(struct_DataReceived));
    m_pDataReceived->size = 2048;
    m_pDataReceived->pData = new char[m_pDataReceived->size];

    StartDebugConsole(h);

    return true;
}
void NW_Fini()
{
    StopSocket();

    if (m_pDataReceived)
    {
        if (m_pDataReceived->pData)
        {
            delete m_pDataReceived->pData; 
        }
        delete m_pDataReceived;
        m_pDataReceived = NULL;
    }

    StopDebugConsole();
}

static DWORD WINAPI RecvThreadProc(LPVOID lpParam)
{
    while (true)
    {
        int byteCount = 0;
        //select
        if ((byteCount = NW_SocketAvailable(m_sockClient, SOCKET_AVAILABLE_TYPE_READ, 20)) == SOCKET_AVAILABLE_TYPE_DROPLINE)
        {
            //check if disconnect by user.If yes....?
            //...

            PrintConsoleLog(WCLao_DEBUG, "drop line...");
            break;
        }
        if (byteCount <= 0)
        {
            continue;
        }
        CStringA s = "";
        s.Format("%d bytes can be Read", byteCount);
        PrintConsoleLog(WCLao_DEBUG, s.GetBuffer());
        //copy data from network    
        //
        int byteCountActual = 0;
        if (byteCount > m_pDataReceived->size - m_pDataReceived->offset)
        {
            //enlarge buffer
            int newSize = m_pDataReceived->offset + byteCount;
            char *buf = new char[newSize];
            memcpy(buf, m_pDataReceived->pData, m_pDataReceived->offset);
            delete m_pDataReceived->pData;
            m_pDataReceived->pData = buf;
            m_pDataReceived->size = newSize;
            PrintConsoleLog(WCLao_DEBUG, "recv buf new size...");
        }
        byteCountActual = ::recv(m_sockClient, m_pDataReceived->pData + m_pDataReceived->offset, byteCount, 0);
        m_pDataReceived->offset += byteCountActual;
        //recv a full packet and post to UI thread
        //
        //check to see if it is at least a package length.If yes,remove to UI layer
        do
        {
            int packageLen = 0;
            if (m_pDataReceived->offset > m_iProtocolHeaderSize)
            {
                int *bodyLen = (int*)(m_pDataReceived->pData + m_iProtocolBodyLen);
                packageLen = m_iProtocolHeaderSize + *bodyLen;
                if (packageLen != 0 && m_pDataReceived->offset >= packageLen)
                {
                    char *bufToUI = new char[packageLen];
                    memcpy(bufToUI, m_pDataReceived->pData, packageLen);
                    memcpy(m_pDataReceived->pData, m_pDataReceived->pData + packageLen, m_pDataReceived->offset - packageLen);
                    m_pDataReceived->offset = m_pDataReceived->offset - packageLen;
                    m_pCB(bufToUI, packageLen);
                    continue;
                }
            }
            break;
        } 
        while(true);
    }
    PrintConsoleLog(WCLao_DEBUG, "recv thread exit from while and exit...");
    m_pCB(NULL, 0);

    return 0;
}
bool NW_PostConnect(char *pszServerIP, int iServerPort)
{
    //init client socket
    m_sockClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(m_sockClient == INVALID_SOCKET)
    {
        OutputDebugInfoW(L"初始化Socket失敗", __FILE__, __FUNCTION__);
        return false;
    }
    u_long ul = 1;
    int iReturn = ::ioctlsocket(m_sockClient, FIONBIO, &ul);//none-blocking I/O
    //connect
    sockaddr_in siServerAddress; 
    siServerAddress.sin_family = AF_INET;
    siServerAddress.sin_port = htons(iServerPort);
    siServerAddress.sin_addr.S_un.S_addr = inet_addr(pszServerIP);
    connect(m_sockClient, (SOCKADDR*)&siServerAddress, sizeof(sockaddr_in));
    if (NW_SocketAvailable(m_sockClient, SOCKET_AVAILABLE_TYPE_WRITE, 10) <= 0)//can read == connect success
    {
        return false;
    }

    m_hRecvThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RecvThreadProc, NULL, 0, 0);

    return true;
}
void NW_DisconnectToServer()
{
    ::closesocket(m_sockClient);
}
bool NW_PostSend(char *pszBuffer, int iLength)
{
    if (NW_SocketAvailable(m_sockClient, SOCKET_AVAILABLE_TYPE_WRITE, 1) <= 0)
    {
        return false;
    }
    int iLengthSent = 0;
    int count = 20;
    int err = 0;
    const int MAX_SEND_ONCE = 1024;
    while (iLengthSent < iLength && count-- > 0)
    {
        if (SOCKET_ERROR == (err = ::send(m_sockClient, pszBuffer, (iLength - iLengthSent > MAX_SEND_ONCE ? MAX_SEND_ONCE : iLength - iLengthSent), 0)))
        {
            SAFE_DELETE(pszBuffer);
            return false;
        }
        iLengthSent += err;
    }
    SAFE_DELETE(pszBuffer);
    if (count == 0)
    {
        return false;
    }
    return true;
}
int NW_SocketAvailable(SOCKET socket, enumSocketAvailableType esat, unsigned 
int iTimeoutSecond)
{
    int ret = 0, readAble;
    int errorcode;
    //check the socket is writeable or not
    FD_SET tbl;
    struct timeval t;
    SOCKET fd = (int)socket;

    //check the availablity
    if(fd <= 0)
    {
        return SOCKET_AVAILABLE_TYPE_OTHER;
    }

    t.tv_sec  = iTimeoutSecond / 1000;
    t.tv_usec = (iTimeoutSecond % 1000) * 1000;

    FD_ZERO(&tbl);
    FD_SET(fd, &tbl);

    switch(esat)
    {
        case SOCKET_AVAILABLE_TYPE_WRITE:
            ret = select(0, NULL, &tbl, NULL, &t);
            break;
        case SOCKET_AVAILABLE_TYPE_READ:
            ret = select(0, &tbl, NULL, NULL, &t);
            break;
        case SOCKET_AVAILABLE_TYPE_BOTH:
            ret = select(0, &tbl, &tbl, NULL, &t);
            break;
        default:
            return SOCKET_AVAILABLE_TYPE_OTHER;
    }

    if(ret == -1)
    {
       if(WSAENOTSOCK == (errorcode = WSAGetLastError()))
       {
            return SOCKET_AVAILABLE_TYPE_DROPLINE;
       }
       return SOCKET_AVAILABLE_TYPE_OTHER;
    }
    else if(ret == 0)
    {
        return SOCKET_AVAILABLE_TYPE_TIMEOUT;
    }
    else
    {
        if(FD_ISSET(fd, &tbl) == 0)
        {
            return SOCKET_AVAILABLE_TYPE_TIMEOUT;
        }
    }

    int size = sizeof(ret);
    //get the available data
    switch(esat)
    {
        case SOCKET_AVAILABLE_TYPE_WRITE:
            getsockopt((int)socket, SOL_SOCKET, SO_SNDBUF, (char*)&ret, &size);
            return ret;//return the available buffer for send
        case SOCKET_AVAILABLE_TYPE_READ:
            if(ioctlsocket((int)socket, FIONREAD, (u_long*)&readAble) < 0)
            {
                readAble = SOCKET_AVAILABLE_TYPE_OTHER;
            }
            if(readAble == 0 && ret > 0)
            {
                readAble = SOCKET_AVAILABLE_TYPE_DROPLINE;
            }
            return readAble;
        case SOCKET_AVAILABLE_TYPE_BOTH:
            if(ioctlsocket((int)socket, FIONREAD, (u_long*)&readAble) < 0)
            {
                readAble = SOCKET_AVAILABLE_TYPE_OTHER;
            }
            return readAble;
        default:
            return SOCKET_AVAILABLE_TYPE_OTHER;
    }
}

Original comment by Giggs...@gmail.com on 30 Jul 2013 at 10:49