上节笔者向大家介绍了Duilib的界面布局并在最后编写了一个仿QQ旋风的界面,但是由于我们屏蔽了系统的标题栏,读者可能已经发现,我们的窗口没办法移动,同样也不能通过拖动来改变窗口的大小。

这就需要我们对WM_NCHITTEST消息进行处理,该消息的LPARAM参数存放鼠标的x坐标和y坐标,在程序中需要对x/y坐标位置进行判断,当坐标落在下图红色线框位置时,我们向窗口过程函数返回HTCAPTION,这样操作系统就会把红色线框区域当成系统的标题栏。

我们可以使用类似的方法告诉Windows操作系统哪里是窗口的右下角,哪里是窗口的边框等等,关于这个消息的更多介绍读者可以参考MSDN。对该消息进行处理算是比较麻烦的,而且对于初学者来说不太好理解,幸运的是Duilib官方为我们封装好了一个WindowImplBase类,该类已经对一些Window消息进行了处理,我们只需要继承这个类就可以了。

笔者对该类稍微进行了修改,类的声明写在win_impl_base.hpp文件中:

  1. #ifndef WIN_IMPL_BASE_HPP
  2. #define WIN_IMPL_BASE_HPP
  3. #include "../DuiLib/StdAfx.h"
  4. #include <Windows.h>
  5. #include <string>
  6. typedef std::basic_string<TCHAR> tString;
  7. using namespace DuiLib;
  8. namespace DuiLib {
  9. class CWindowWnd;
  10. class INotifyUI;
  11. class IMessageFilterUI;
  12. class IDialogBuilderCallback;
  13. }
  14. class WindowImplBase : public CWindowWnd, public INotifyUI, public IMessageFilterUI, public IDialogBuilderCallback
  15. {
  16. public:
  17. WindowImplBase();
  18. virtual ~WindowImplBase();
  19. virtual void OnFinalMessage(HWND hWnd);
  20. virtual UINT GetClassStyle() const;
  21. virtual void Init();
  22. virtual CControlUI* CreateControl(LPCTSTR pstrClass);
  23. virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled);
  24. virtual LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  25. virtual LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  26. #if defined(WIN32) && !defined(UNDER_CE)
  27. virtual LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  28. virtual LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  29. virtual LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  30. virtual LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  31. virtual LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  32. virtual LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  33. #endif
  34. virtual LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  35. virtual LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  36. virtual LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  37. virtual LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  38. virtual LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  39. virtual LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  40. virtual LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  41. virtual LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  42. virtual LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  43. virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  44. virtual LRESULT HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  45. protected:
  46. virtual tString GetSkinFolder();
  47. virtual tString GetSkinFile() = 0;
  48. virtual LRESULT ResponseDefaultKeyEvent(WPARAM wParam);
  49. protected:
  50. CPaintManagerUI paint_manager_;
  51. };
  52. #endif // WIN_IMPL_BASE_HPP

下面是一些成员函数的实现部分,写在win_impl_base.cpp文件中:


  1. #include "win_impl_base.hpp"
  2. WindowImplBase::WindowImplBase()
  3. {}
  4. WindowImplBase::~WindowImplBase()
  5. {}
  6. UINT WindowImplBase::GetClassStyle() const
  7. {
  8. return CS_DBLCLKS;
  9. }
  10. CControlUI* WindowImplBase::CreateControl(LPCTSTR pstrClass)
  11. {
  12. return NULL;
  13. }
  14. void WindowImplBase::OnFinalMessage(HWND /*hWnd*/)
  15. {
  16. paint_manager_.RemovePreMessageFilter(this);
  17. paint_manager_.RemoveNotifier(this);
  18. paint_manager_.ReapObjects(paint_manager_.GetRoot());
  19. }
  20. void WindowImplBase::Init()
  21. {}
  22. LRESULT WindowImplBase::OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  23. {
  24. bHandled = FALSE;
  25. return 0;
  26. }
  27. LRESULT WindowImplBase::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  28. {
  29. bHandled = FALSE;
  30. return 0;
  31. }
  32. #if defined(WIN32) && !defined(UNDER_CE)
  33. LRESULT WindowImplBase::OnNcActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
  34. {
  35. if( ::IsIconic(*this) ) bHandled = FALSE;
  36. return (wParam == 0) ? TRUE : FALSE;
  37. }
  38. LRESULT WindowImplBase::OnNcCalcSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  39. {
  40. return 0;
  41. }
  42. LRESULT WindowImplBase::OnNcPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  43. {
  44. return 0;
  45. }
  46. LRESULT WindowImplBase::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  47. {
  48. POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
  49. ::ScreenToClient(*this, &pt);
  50. RECT rcClient;
  51. ::GetClientRect(*this, &rcClient);
  52. if( !::IsZoomed(*this) ) {
  53. RECT rcSizeBox = paint_manager_.GetSizeBox();
  54. if( pt.y < rcClient.top + rcSizeBox.top ) {
  55. if( pt.x < rcClient.left + rcSizeBox.left ) return HTTOPLEFT;
  56. if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;
  57. return HTTOP;
  58. }
  59. else if( pt.y > rcClient.bottom - rcSizeBox.bottom ) {
  60. if( pt.x < rcClient.left + rcSizeBox.left ) return HTBOTTOMLEFT;
  61. if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;
  62. return HTBOTTOM;
  63. }
  64. if( pt.x < rcClient.left + rcSizeBox.left ) return HTLEFT;
  65. if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;
  66. }
  67. RECT rcCaption = paint_manager_.GetCaptionRect();
  68. if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
  69. && pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {
  70. CControlUI* pControl = static_cast<CControlUI*>(paint_manager_.FindControl(pt));
  71. if( pControl && _tcsicmp(pControl->GetClass(), _T("ButtonUI")) != 0 &&
  72. _tcsicmp(pControl->GetClass(), _T("OptionUI")) != 0 /*&&
  73. _tcsicmp(pControl->GetClass(), _T("TextUI")) != 0 */)
  74. return HTCAPTION;
  75. }
  76. return HTCLIENT;
  77. }
  78. LRESULT WindowImplBase::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  79. {
  80. MONITORINFO oMonitor = {};
  81. oMonitor.cbSize = sizeof(oMonitor);
  82. ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
  83. CRect rcWork = oMonitor.rcWork;
  84. rcWork.Offset(-rcWork.left, -rcWork.top);
  85. LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
  86. lpMMI->ptMaxPosition.x = rcWork.left;
  87. lpMMI->ptMaxPosition.y = rcWork.top;
  88. lpMMI->ptMaxSize.x = rcWork.right;
  89. lpMMI->ptMaxSize.y = rcWork.bottom;
  90. bHandled = FALSE;
  91. return 0;
  92. }
  93. LRESULT WindowImplBase::OnMouseWheel(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  94. {
  95. bHandled = FALSE;
  96. return 0;
  97. }
  98. #endif
  99. LRESULT WindowImplBase::OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  100. {
  101. bHandled = FALSE;
  102. return 0;
  103. }
  104. LRESULT WindowImplBase::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  105. {
  106. bHandled = FALSE;
  107. return 0;
  108. }
  109. LRESULT WindowImplBase::OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  110. {
  111. bHandled = FALSE;
  112. return 0;
  113. }
  114. LRESULT WindowImplBase::OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  115. {
  116. bHandled = FALSE;
  117. return 0;
  118. }
  119. LRESULT WindowImplBase::OnKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  120. {
  121. bHandled = FALSE;
  122. return 0;
  123. }
  124. LRESULT WindowImplBase::OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  125. {
  126. bHandled = FALSE;
  127. return 0;
  128. }
  129. LRESULT WindowImplBase::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  130. {
  131. SIZE szRoundCorner = paint_manager_.GetRoundCorner();
  132. #if defined(WIN32) && !defined(UNDER_CE)
  133. if( !::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0) ) {
  134. CRect rcWnd;
  135. ::GetWindowRect(*this, &rcWnd);
  136. rcWnd.Offset(-rcWnd.left, -rcWnd.top);
  137. rcWnd.right++; rcWnd.bottom++;
  138. HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
  139. ::SetWindowRgn(*this, hRgn, TRUE);
  140. ::DeleteObject(hRgn);
  141. }
  142. #endif
  143. bHandled = FALSE;
  144. return 0;
  145. }
  146. LRESULT WindowImplBase::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  147. {
  148. if (wParam == SC_CLOSE){
  149. bHandled = TRUE;
  150. return 0;
  151. }
  152. #if defined(WIN32) && !defined(UNDER_CE)
  153. BOOL bZoomed = ::IsZoomed(*this);
  154. LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  155. if( ::IsZoomed(*this) != bZoomed ){
  156. }
  157. #else
  158. LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  159. #endif
  160. return lRes;
  161. }
  162. tString WindowImplBase::GetSkinFolder()
  163. {
  164. return tString(CPaintManagerUI::GetInstancePath()); //+ _T("skin\\");
  165. }
  166. LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  167. {
  168. LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
  169. styleValue &= ~WS_CAPTION;
  170. ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  171. RECT rcClient;
  172. ::GetClientRect(*this, &rcClient);
  173. ::SetWindowPos(*this, NULL, rcClient.left, rcClient.top, rcClient.right - rcClient.left, \
  174. rcClient.bottom - rcClient.top, SWP_FRAMECHANGED);
  175. paint_manager_.Init(m_hWnd);
  176. paint_manager_.AddPreMessageFilter(this);
  177. CDialogBuilder builder;
  178. //paint_manager_.SetResourcePath(GetSkinFolder().c_str());
  179. //tString tstrSkin = paint_manager_.GetResourcePath();
  180. tString tstrSkin = GetSkinFile();
  181. CControlUI* pRoot = builder.Create(tstrSkin.c_str(), (UINT)0, this, &paint_manager_);
  182. paint_manager_.AttachDialog(pRoot);
  183. paint_manager_.AddNotifier(this);
  184. Init();
  185. return 0;
  186. }
  187. LRESULT WindowImplBase::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  188. {
  189. bHandled = FALSE;
  190. return 0;
  191. }
  192. LRESULT WindowImplBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  193. {
  194. LRESULT lRes = 0;
  195. BOOL bHandled = TRUE;
  196. switch (uMsg)
  197. {
  198. case WM_CREATE: lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
  199. case WM_CLOSE: lRes = OnClose(uMsg, wParam, lParam, bHandled); break;
  200. case WM_DESTROY: lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;
  201. #if defined(WIN32) && !defined(UNDER_CE)
  202. case WM_NCACTIVATE: lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
  203. case WM_NCCALCSIZE: lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
  204. case WM_NCPAINT: lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
  205. case WM_NCHITTEST: lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
  206. case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break;
  207. case WM_MOUSEWHEEL: lRes = OnMouseWheel(uMsg, wParam, lParam, bHandled); break;
  208. #endif
  209. case WM_SIZE: lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
  210. case WM_SYSCOMMAND: lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break;
  211. case WM_KEYDOWN: lRes = OnKeyDown(uMsg, wParam, lParam, bHandled); break;
  212. case WM_KILLFOCUS: lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); break;
  213. case WM_SETFOCUS: lRes = OnSetFocus(uMsg, wParam, lParam, bHandled); break;
  214. case WM_LBUTTONUP: lRes = OnLButtonUp(uMsg, wParam, lParam, bHandled); break;
  215. case WM_LBUTTONDOWN: lRes = OnLButtonDown(uMsg, wParam, lParam, bHandled); break;
  216. case WM_MOUSEMOVE: lRes = OnMouseMove(uMsg, wParam, lParam, bHandled); break;
  217. default: bHandled = FALSE; break;
  218. }
  219. if (bHandled) return lRes;
  220. lRes = HandleCustomMessage(uMsg, wParam, lParam, bHandled);
  221. if (bHandled) return lRes;
  222. if (paint_manager_.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
  223. return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  224. }
  225. LRESULT WindowImplBase::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, bool& /*bHandled*/)
  226. {
  227. if (uMsg == WM_KEYDOWN)
  228. {
  229. switch (wParam)
  230. {
  231. case VK_RETURN:
  232. case VK_ESCAPE:
  233. return ResponseDefaultKeyEvent(wParam);
  234. default:
  235. break;
  236. }
  237. }
  238. return FALSE;
  239. }
  240. LRESULT WindowImplBase::ResponseDefaultKeyEvent(WPARAM wParam)
  241. {
  242. if (wParam == VK_RETURN)
  243. {
  244. return FALSE;
  245. }
  246. else if (wParam == VK_ESCAPE)
  247. {
  248. Close();
  249. return TRUE;
  250. }
  251. return FALSE;
  252. }

我们需要將这两个文件添加到自己的工程中,项目结构如下图所示:

在我们的程序中不再继承CWindowWnd和INotifyUI这两个类,而是直接继承WindowImplBase,重写父类的GetWindowClassName、GetClassStyle、GetSkinFile、Notify四个函数即可:

  1. #include "win_impl_base.hpp"
  2. #include <Windows.h>
  3. class MyWnd : public WindowImplBase
  4. {
  5. LPCTSTR GetWindowClassName() const
  6. {
  7. return L"MyWnd";
  8. }
  9. UINT GetClassStyle() const{
  10. return UI_CLASSSTYLE_FRAME|CS_DBLCLKS;
  11. }
  12. tString GetSkinFile(){
  13. return L"tutorial5.xml";
  14. }
  15. void Notify(TNotifyUI& msg)
  16. {
  17. if(msg.sType == L"click")
  18. {
  19. if(msg.pSender->GetName() == L"CloseBtn")
  20. {
  21. ::PostQuitMessage(0);
  22. }else if(msg.pSender->GetName() == L"MinBtn")
  23. {
  24. ::SendMessage(m_hWnd,WM_SYSCOMMAND, SC_MINIMIZE, 0);
  25. }
  26. }
  27. }
  28. };
  29. INT WinMain(HINSTANCE hInst,HINSTANCE hPreInst,LPSTR lpCmdLine,INT Show)
  30. {
  31. CPaintManagerUI::SetInstance(hInst);
  32. CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetResourcePath());
  33. //创建主窗口
  34. MyWnd* pFrame = new MyWnd();
  35. pFrame->Create(NULL,L"Tutorial5",UI_WNDSTYLE_FRAME^WS_THICKFRAME,WS_EX_WINDOWEDGE);
  36. pFrame->CenterWindow();
  37. pFrame->ShowWindow(true);
  38. CPaintManagerUI::MessageLoop();
  39. return 0;
  40. }

我们只需要在GetSkinFile方法中返回一个界面布局文件名称,比上节简单多了吧,编译运行看到上节的界面能够成功加载而且已经可以拖动了。

博文源码:https://github.com/rongbo-j/duilib-tutorial

DirectUI界面编程(五)WindowImplBase的使用的更多相关文章

  1. DirectUI界面编程(一)创建第一个应用

    1.获取Duilib库文件 通过上一节大家对DirectUI界面设计有了初步的了解,本节开始我们一起学习Duilib界面库的使用. 首先我们需要获取Duilib库,目前最新版本为2.0,最新版本源码托 ...

  2. DirectUI界面编程(零)简介

    有过Win32.MFC编程经验的朋友应该都知道,传统Windows应用中的按钮.编辑框等控件都是一个子窗口,操作系统通过窗口句柄来唯一标识该窗口. 使用Windows 标准控件创建用户界面,美化起来是 ...

  3. DirectUI界面编程(六)实现右键弹出菜单

    本节向大家介绍一下右键弹出菜单是如何实现的.效果如下,在窗口中点击鼠标右键弹出菜单,点击菜单项能够响应菜单点击事件. 使用Duilib库实现的弹出菜单,实际上也是一个Windows窗口,因此我们需要创 ...

  4. DirectUI界面编程(四)界面布局详解

    Duilib的界面布局使用xml文件进行描述,在Duilib v1.1版本的xml布局文件中我们可以使用以下这些标签(后续版本标签有扩充): 这些标签总的来讲可以分为三类: 窗口类,该类别中只有一个W ...

  5. DirectUI界面编程(三)从XML文件中加载界面

    Duilib支持xml界面布局,使得界面设计与逻辑处理相分离,本节介绍如何从xml文件中加载界面元素. 我们需要以下几个步骤: 创建并初始化CPaintManagerUI对象. 创建CDialogBu ...

  6. DirectUI界面编程(二)绘制一个按钮

    上节介绍了使用源码方式构建Duilib应用的项目配置,并创建了一个最简单的基于Duilib库的窗口,细心的读者会发现,当我们点击窗口的关闭按钮时,应用并没有真的退出,因为我们并没有对窗口事件进行处理, ...

  7. Windows界面编程第五篇 静态控件背景透明化(13篇)

    上一篇<Windows界面编程第三篇 异形窗体 普通版>和<Windows界面编程第四篇异形窗体 高富帅版>介绍了异形窗口(异形窗体)的创建,并总结出了异形窗口的“三要素”: ...

  8. 开源的DirectUI界面库

    1. duilib简介 duilib是一个开源的DirectUI界面库,简洁但是功能强大.而且还是BSD的license,所以即便是在商业上,大家也可以安心使用.现在大家可以从这个网站获取到他们所有的 ...

  9. Java中的图形界面编程

    前言 正文 Java中的图形界面编程 AWT/Swing AWT(Abstract Window ToolKits,抽象窗体工具集) 1.容器类:用来存储组件,实现容器布局 2.组件类:实现界面的一些 ...

随机推荐

  1. Outlook2010规则:尝试操作失败,找不到某个对象

    可以尝试通过清除规则的方法 启动 Outlook 并删除基于客户端的规则:outlook /cleanclientrules 如果失败,再执行这句 启动 Outlook 并删除基于服务器端的规则:ou ...

  2. Robot Framework(二)测试数据语法

    2.1.1文件和目录 测试数据的层次结构安排如下: 测试数据在测试数据文件中创建. 测试数据文件会自动创建一个包含该文件中的测试数据的测试套件. 包含测试数据文件的目录构成了更高级别的测试套件.这样的 ...

  3. websocket 进阶!netty框架实现websocket达到高并发

    引言: 在前面两篇文章中,我们对原生websocket进行了了解,且用demo来简单的讲解了其用法.但是在实际项目中,那样的用法是不可取的,理由是tomcat对高并发的支持不怎么好,特别是tomcat ...

  4. nginx日志按日期自动切割脚本

    #!/bin/bash #nginx日志切割脚本 #author:setevn #设置日志文件存放目录 logs_path="/usr/local/nginx/logs/" #设置 ...

  5. 商品的CRUD操作

    (1)新增商品:新增文档,建立索引 PUT /index/type/id{ "json数据"} PUT /ecommerce/product/1{ "name" ...

  6. linux内核内存分配(一、基本概念)

    内存分配是Linux比较复杂也是比较重要的部分,这个和ssd驱动很类似:物理地址和虚拟地址的映射关系.下面总结下最近看到的有关内存分配的内容和自己的理解: 1.一致内存访问和非一致内存访问 上图来自& ...

  7. jquery.lazyload滚动不起作用

    昨天同事在开发图片懒加载功能时用到了lazyload,使用相当标准,然而结果却不如人意,在滚动时未能起作用.引用https://cdn.bootcss.com/jquery_lazyload/1.9. ...

  8. 一、简介 ELO商户类别推荐有助于了解客户忠诚度

    Elo Merchant Category Recommendation Help understand customer loyalty (ELO商户类别推荐有助于了解客户忠诚度) 竞赛描述: 想象 ...

  9. UVA455 - Periodic Strings(紫书习题3.4)

    如果一个字符串可以被某个长度为k的字符串重复多次得到,则称这个字符串的周期为k.例如,字符串"abcabcabcabc"以3为周期(当然,他也以6.12等等为周期).  现在请你编 ...

  10. P2024 食物链 (补集)

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...