首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder 實作 Windows 2000 Messenger:多執行緒、網路枚舉與系統匣整合

     編輯:關於C++

專案架構與關鍵技術

  • 多執行緒:UI 執行緒負責介面,背景執行緒處理網路枚舉與訊息發送,避免介面凍結。
  • 網路枚舉:WNetOpenEnum/WNetEnumResource 遞迴列舉網域/電腦/共享資源。
  • Unicode 轉換:AnsiString ↔ WideChar 相容 Messenger API。
  • 不規則視窗:自訂視窗區域 (Region) 實現非矩形介面。
  • 系統匣:TrayIcon 元件最小化至通知區域,支援右鍵選單還原/結束。
  • 自動啟動:寫入 HKCU\Software\Microsoft\Windows\CurrentVersion\Run。

介面配置

主表單包含:TTreeView (網路結構)、TListView (線上用戶)、TMemo (輸入訊息)、TStatusBar、工具列按鈕 (發送、匿名、要求回執)、系統匣圖示。

Messenger 介面配置

核心程式碼片段

發送訊息 (按鈕事件)


void __fastcall TFormMain::ButtonSendClick(TObject *Sender) {
    AnsiString msg = Memo1->Text;
    if (msg.IsEmpty()) { ShowMessage("請輸入訊息"); return; }

    AnsiString from = CheckBoxAnony->Checked ? EditAnony->Text : "";
    AnsiString to;
    TListItem* item;

    if (!ListView1->SelCount) {  // TreeView 選取
        if (!TreeView1->Selected) { ShowMessage("請選擇目標"); return; }
        to = TreeView1->Selected->Text;
        if (TreeView1->Selected->Level == 1) to += "*";  // 電腦節點加 *
    } else {  // ListView 多選
        for (int i = 0; i < ListView1->SelCount; i++) {
            item = (i==0) ? ListView1->Selected : ListView1->GetNextItem(item, sdAll, TItemStates() << isSelected);
            to = item->Caption;
            if (TreeView1->Selected->Level == 0) to += "*";  // 網域節點
            while (to[1] == '\\') to = to.SubString(2, to.Length()-1);  // 移除前導 \\
            new TNetMessageSend(false, to, from, msg, CheckBoxGetRet->Checked);
        }
        return;
    }

    while (to[1] == '\\') to = to.SubString(2, to.Length()-1);
    new TNetMessageSend(false, to, from, msg, CheckBoxGetRet->Checked);
}

網路枚舉執行緒


bool __fastcall TEnumNetResource::GetNetRes(TTreeNodes* Nodes, TTreeNode* Node,
    NETRESOURCE* pNetRes, int Depth) {
    if (Terminated || !Nodes || Depth == 0) return false;

    HANDLE hEnum;
    if (WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, pNetRes, &hEnum) != NO_ERROR)
        return false;

    NETRESOURCE buffer[1024];
    DWORD count = 10, size = 16384;
    bool result = true;

    do {
        DWORD err = WNetEnumResource(hEnum, &count, buffer, &size);
        if (err == NO_ERROR) {
            for (DWORD i = 0; i < count; i++) {
                if (Terminated) return false;
                NETRESOURCE* nr = &buffer[i];
                AnsiString name = nr->lpRemoteName;
                while (name[1] == '\\') name = name.SubString(2, name.Length()-1);
                TTreeNode* child = Nodes->AddChild(Node, name);
                // 設定圖示索引...
                if (nr->dwDisplayType != RESOURCEDISPLAYTYPE_SHARE)
                    GetNetRes(Nodes, child, nr, Depth-1);
            }
        } else if (err != ERROR_NO_MORE_ITEMS) {
            result = false; break;
        }
    } while (count == 10);

    WNetCloseEnum(hEnum);
    return result;
}

訊息發送執行緒 (NetMessageBufferSend)


void __fastcall TNetMessageSend::Execute() {
    const int MAXLEN = 1600;
    wchar_t* buf = new wchar_t[FMessage.WideCharBufSize()];
    FMessage.WideChar(buf, FMessage.WideCharBufSize());

    for (int offset = 0; offset < FMessage.WideCharBufSize()*2; offset += MAXLEN) {
        int len = min(MAXLEN, FMessage.WideCharBufSize()*2 - offset);
        DWORD ret = NetMessageBufferSend(NULL, FUserName.c_str(), FFromName.c_str(),
            (char*)(buf + offset/2), len);
        // 處理回傳碼...
    }
    delete[] buf;
}

部署與測試環境

  • 開發環境:C++Builder 6.0
  • 目標平台:Windows 2000 Professional
  • 需啟用 Messenger 服務 (services.msc → Messenger → 自動/啟動)
  • 防火牆需開放 UDP 137/138、TCP 139/445 (NetBIOS/SMB)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved