日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IPMsg

發布時間:2024/1/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IPMsg 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡單介紹:

IP Messenger :?http://ipmsg.org?(p.s.:該網站的右上角有英文版網頁鏈接)

島國H.Shirouzu寫的跨平臺局域網通信開源軟件,基于TCP/IP,不需要服務器。
國內大家用的Feiq(飛秋)就是作者基于IPMsg寫的,目前更新到r3.42。




初學tcp/ip的盆友不妨把source code抓下來讀一讀,ipmsg自己定義了一套應用層協議,消息的收發基于udp協議,文件的收發基于tcp。

我記得學校里最初學tcp/ip時,教的是c/s模型的socket編程,先寫個server在那兒一直while(1),這邊再啟動幾個client,如此,一個簡單的局域網通信軟件就寫好了。

ipmsg source code里面有對ipmsg protocol作說明,基于日文有其它程序員翻譯成了英文的prot-eng.txt。 如,啟動或退出時通過向(255.255.255.255)廣播的方式把消息發出去。

話說此文不會針對IPMsg協議來寫,主要還是Win32流程的東西。上一稿《Win32 application (1) Begin》,講到vs創建win32 app后,就沒有下文了,今天接著寫我的。關于Win32應用的流程介紹蜘蛛網上有很多高質量的網文,請大家自行使用搜索引擎。

關于ipmsg的source code的話,有幾點需要說明:

1.作者貌似是用vs2005寫的,我把代碼資源些都放到vs2012面,直接是編不過的,至于怎么解決,我也不知道,有誰知道的話不妨留言分享一下,thanks。

2.Source code里面的很多注釋都是日文寫的,我用VS2012沒有亂碼出現,如果你用Source Insight或其它,可能需要再配置一下字體什么的,讓它支持日文顯示。

3.external:


使用了libpng & zlib.

4. src:


install是面的source code及resource file都是用于安裝ipmsg時的GUI顯示及邏輯處理;

uninst則反之;

TLib則是ipmsg軟件的主要基類:



用VS查看類圖:

1)TApp


2) TWin


按照實現Win32 applicaiton的流程來看ipmsg中Win32部分的流程:

1. WinMain入口

2.?Registers the window class. --> 注冊需要掛一個callback function(To processes messages for the main window.)

3. Application initialization: saves instance handle and creates main window

4.?Main message loop


ipmsg.cpp最后定義了WinMain:

int WINAPI WinMain(HINSTANCE hI, HINSTANCE, LPSTR cmdLine, int nCmdShow) {if (IsWin95()) {MessageBox(0, "Please use old version (v2.06 or earlier)","Win95/98/Me is not supported", MB_OK);::ExitProcess(0xffffffff);return 0;}TMsgApp app(hI, cmdLine, nCmdShow);return app.Run(); } 定義了一個TMsgApp類的對象,從前面的類圖知道TMsgApp是從TApp繼承過來的。TMsgApp沒有重新定義Run(),所以多態地直接調用父類的Run():

int TApp::Run(void) {MSG msg;InitApp();InitWindow();while (::GetMessage(&msg, NULL, 0, 0)){if (PreProcMsg(&msg))continue;::TranslateMessage(&msg);::DispatchMessage(&msg);}return (int)msg.wParam; } 現在可以看出,Run()和我們用VS直接自動生成的WinMain函數:

1) InitApp注冊窗口類;

2) InitWindow實例化窗口;

3) 最后消息處理循環。


1)?InitApp注冊窗口類,并掛載WinProc處理Window Message

BOOL TApp::InitApp(void) // reference kwc {WNDCLASSW wc;memset(&wc, 0, sizeof(wc));wc.style = (CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS);wc.lpfnWndProc = WinProc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hI;wc.hIcon = NULL;wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = NULL;wc.lpszMenuName = NULL;wc.lpszClassName = (LPCWSTR)defaultClassV;if (::FindWindowV(defaultClassV, NULL) == NULL){if (::RegisterClassV(&wc) == 0)return FALSE;}return TRUE; } TApp類實現的WinProc():
LRESULT CALLBACK TApp::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {TApp *app = TApp::GetApp();TWin *win = app->SearchWnd(hWnd);if (win)return win->WinProc(uMsg, wParam, lParam);if ((win = app->preWnd)){app->preWnd = NULL;app->AddWinByWnd(win, hWnd);return win->WinProc(uMsg, wParam, lParam);}return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } 可以看出,TApp作為父類,通過傳遞進來的窗口HANDLE找到對應的Window,并調用Window的消息處理函數。

這里會調用到TWin類的WinProc():

LRESULT TWin::WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam) {BOOL done = FALSE;LRESULT result = 0;switch(uMsg){case WM_CREATE:GetWindowRect(&orgRect);done = EvCreate(lParam);break;case WM_CLOSE:done = EvClose();break;case WM_COMMAND:done = EvCommand(HIWORD(wParam), LOWORD(wParam), lParam);break;case WM_SYSCOMMAND:done = EvSysCommand(wParam, MAKEPOINTS(lParam));break;case WM_TIMER:done = EvTimer(wParam, (TIMERPROC)lParam);break;case WM_DESTROY:done = EvDestroy();break;/* other case */ }

TWin作為主窗口類,ipmsg從TWin繼承了很多的子類,TMainWin是其中一個。

2) InitWindow實例化窗口TApp將InitWindow()聲明為virtual,需要子類來實現,下面是

TMsgApp類實現的InitWindow():

void TMsgApp::InitWindow(void) {HWND hWnd;char class_name[MAX_PATH_U8] = IPMSG_CLASS, *tok, *msg, *p;char *class_ptr = NULL;ULONG nicAddr = 0;int port_no = atoi(cmdLine);BOOL show_history = FALSE;enum Stat { ST_NORMAL, ST_TASKBARUI_MSG, ST_EXIT, ST_ERR } status = ST_NORMAL;int taskbar_msg = 0;int taskbar_cmd = 0;/* ... ... something ... ... */HANDLE hMutex = ::CreateMutex(NULL, FALSE, class_name);::WaitForSingleObject(hMutex, INFINITE);if ((hWnd = FindWindowU8(class_name)) ||!TRegisterClassU8(class_name, CS_DBLCLKS, ::LoadIcon(hI, (LPCSTR)IPMSG_ICON),::LoadCursor(NULL, IDC_ARROW))) {if (hWnd) ::SetForegroundWindow(hWnd);::ExitProcess(0xffffffff);return;}mainWnd = new TMainWin(nicAddr, port_no);mainWnd->Create(class_name);::ReleaseMutex(hMutex);::CloseHandle(hMutex);if (show_history) mainWnd->SendMessage(WM_COMMAND, MENU_HELP_HISTORY, 0); }
從后面可以看到mainWnd被實例化為一個TMainWin類的對象,并調用TMainWin類的create函數來創建main window;繼續跟下去會發現它最終調用到了TWin的CreateV():

BOOL TWin::CreateV(const void *className, const void *title, DWORD style, DWORD exStyle,HMENU hMenu) {if (className == NULL) {className = TApp::GetApp()->GetDefaultClassV();}TApp::GetApp()->AddWin(this);if ((hWnd = ::CreateWindowExV(exStyle, className, title, style,rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,parent ? parent->hWnd : NULL, hMenu, TApp::GetInstance(), NULL)) == NULL)return TApp::GetApp()->DelWin(this), FALSE;elsereturn TRUE; }
reateWindowExV()被不是Windows SDK提供的API,而只是TLib里定義的一個函數指針:

HWND (WINAPI *CreateWindowExV)(DWORD exStyle, const void *className, const void *title,DWORD style, int x, int y, int nw, int nh, HWND hParent, HMENU hMenu, HINSTANCE hI,void *param);
如果是在Windows系統中跑,它最終會指向CreateWindowExW這個Windows API。

至此,實例化窗口順序調用就完成了,不過并沒有看到主窗口是怎么設計的,它只不過創建了一個窗口,僅此而已,并且,沒有看到Show&Update。當然這是在WinProc里收到WM_CREATE里面來做的,主窗口的EvCreate:

LRESULT TWin::WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam) {BOOL done = FALSE;LRESULT result = 0;switch(uMsg){case WM_CREATE:GetWindowRect(&orgRect);done = EvCreate(lParam);break;/* other case */} }
從TWin類繼承來的TMainWin重新定義了WinProc函數:

BOOL TMainWin::EvCreate(LPARAM lParam) {hMainWnd = hWnd;mainWin = this;if (IsWinVista() && TIsUserAnAdmin() && TIsEnableUAC()) {TChangeWindowMessageFilter(WM_DROPFILES, 1);TChangeWindowMessageFilter(WM_COPYDATA, 1);TChangeWindowMessageFilter(WM_COPYGLOBALDATA, 1);TChangeWindowMessageFilter(WM_CLOSE, 1);}if (!msgMng->GetStatus()) return TRUE;if (cfg->TaskbarUI) {Show(SW_MINIMIZE);} else {Show(SW_HIDE);}while (!TaskTray(NIM_ADD, hMainIcon, IP_MSG)) {Sleep(1000); // for logon script}TaskBarCreateMsg = ::RegisterWindowMessage("TaskbarCreated");TaskBarButtonMsg = ::RegisterWindowMessage("TaskbarButtonCreated");TaskBarNotifyMsg = ::RegisterWindowMessage(IP_MSG);SetIcon(cfg->AbsenceCheck ? hRevIcon : hMainIcon);SetCaption();if (!SetupCryptAPI(cfg, msgMng)) MessageBoxU8("CryptoAPI can't be used. Setup New version IE");msgMng->AsyncSelectRegister(hWnd);SetHotKey(cfg);if (msgMng->GetStatus()) {EntryHost();}if (IsWin7()) { // for TaskbarUI::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (cfg->TaskbarUI) {CreateJumpList(className);}else { // DeleteJumpList();}}::SetTimer(hWnd, IPMSG_CLEANUP_TIMER, 60000, NULL); // 1minreturn TRUE; }
Show Window: Show(SW_HIDE); 調用Windows API。IPMsg啟動后會自動最小化,所以你不會看到有一個主窗口界面出現,不過它的確已經創建了一個main window,當然嘗試點擊右下角的圖標來打開IPMsg時,會觸發BUTTON事件,WinProc會去處理WM_LBUTTONUP消息, 用來Send Msg的窗口就會打開。

void TWin::Show(int mode) {::ShowWindow(hWnd, mode);::UpdateWindow(hWnd); }
3) 最后消息處理循環

while (::GetMessage(&msg, NULL, 0, 0)){if (PreProcMsg(&msg))continue;::TranslateMessage(&msg);::DispatchMessage(&msg);}
其中,PreProcMsg()是為了將msg傳遞給對應的窗口去處理,自己的娃自己管好,你不管,就要交給父輩來管。最后最后,就是編寫各種消息處理函數了,當然Win32主流程當中也有不少細節在這里沒有說,大家不妨自己抓份source code來讀一讀。上一個post中提到Win32 application開發,各種蛋疼,其中一個原因就是Win32沒有像WinForm或WPF那樣可以直接拖動控件來布局應用的圖形界面,其實Win32是有的,Windows SDK已經提供了一些基本的控件給Win32開發人員。



用這些控件前需要調用?InitCommonControls()或者InitCommonControlsEx()來初始化一下,這個函數在Commctrl.h里聲明的。


這是IPMsg用來發消息的Dialog窗口,當然啰,要做出Tencent QQ那樣的漂亮界面,還需要自己去定制一些界面庫來實現。




總結

以上是生活随笔為你收集整理的IPMsg的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。