当前位置: 首页 > news >正文

信息技术做网站seo百度快照优化公司

信息技术做网站,seo百度快照优化公司,wordpress如何设置用户登录,华汇建设集团有限公司网站QEventLoop屏蔽了底层消息循环实现细节#xff0c;向上提供了与平台无关的消息/事件循环。 本文拟对Windows系统下QEventLoop的实现原理予以分析。 注1#xff1a;限于研究水平#xff0c;分析难免不当#xff0c;欢迎批评指正。 注2#xff1a;文章内容会不定期更新。 …QEventLoop屏蔽了底层消息循环实现细节向上提供了与平台无关的消息/事件循环。 本文拟对Windows系统下QEventLoop的实现原理予以分析。 注1限于研究水平分析难免不当欢迎批评指正。 注2文章内容会不定期更新。 一、研究素材Win32应用程序框架 在Win32应用程序中wWinMain是整个程序的入口点整个代码段主要包括窗口类注册、创建窗口、消息循环等。 int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPWSTR lpCmdLine,_In_ int nCmdShow) {UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// TODO: Place code here.// Initialize global stringsLoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}HACCEL hAccelTable LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));MSG msg;// Main message loop:while (GetMessage(msg, nullptr, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg)){TranslateMessage(msg);DispatchMessage(msg);}}return (int) msg.wParam; } MyRegisterClass用于注册创库类可以指定窗口样式、窗口过程函数等。 // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // ATOM MyRegisterClass(HINSTANCE hInstance) {WNDCLASSEXW wcex;wcex.cbSize sizeof(WNDCLASSEX);wcex.style CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc WndProc;wcex.cbClsExtra 0;wcex.cbWndExtra 0;wcex.hInstance hInstance;wcex.hIcon LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));wcex.hCursor LoadCursor(nullptr, IDC_ARROW);wcex.hbrBackground (HBRUSH)(COLOR_WINDOW1);wcex.lpszMenuName MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);wcex.lpszClassName szWindowClass;wcex.hIconSm LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassExW(wcex); } 完成窗口类注册之后可以依据窗口类创建窗口实例 // // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {hInst hInstance; // Store instance handle in our global variableHWND hWnd CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE; } 当完成窗口类注册之后便可以依据窗口类名称来创建窗口。在Windows系统下消息队列用于管理线程内窗口相关的消息同一线程内的窗口对象共享同一各消息队列。 The Message Loop For each thread that creates a window, the operating system creates a queue for window messages. This queue holds messages for all the windows that are created on that thread.  MSG msg;// Main message loop:while (GetMessage(msg, nullptr, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg)){TranslateMessage(msg);DispatchMessage(msg);}} 当消息被投递到窗口时便会调用对应的窗口过程函数 // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {switch (message){case WM_COMMAND:{int wmId LOWORD(wParam);// Parse the menu selections:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}}break;case WM_PAINT:{PAINTSTRUCT ps;HDC hdc BeginPaint(hWnd, ps);// TODO: Add any drawing code that uses hdc here...EndPaint(hWnd, ps);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0; } 二、QEventLoop实现原理 QEventLoop实际上是通过QAbstractEventDispatcher子类来屏蔽了底层窗口系统的消息循环。 bool QEventLoop::processEvents(ProcessEventsFlags flags) {Q_D(QEventLoop);if (!d-threadData-hasEventDispatcher())return false;return d-threadData-eventDispatcher.loadRelaxed()-processEvents(flags); } 从中可以看出QAbstractEventDispatcher是线程级别的存在每个线程有唯一的QAbstractEventDispatcher实现线程内的所有QEventLoop共享同一个QAbstractEventDispatcher实现。 2.1 QEventDispatcherWin32的创建 实际上在Windows系统下当创建QCoreApplication时便会创建主线程相关的QEventDispatcherWin32而QEventDispatcherWin32正是QAbstractEventDispatcher的Windows系统实现。 void QCoreApplicationPrivate::init() {// ... #ifndef QT_NO_QOBJECT// use the event dispatcher created by the app programmer (if any)Q_ASSERT(!eventDispatcher);eventDispatcher threadData-eventDispatcher.loadRelaxed();// otherwise we create oneif (!eventDispatcher)createEventDispatcher();Q_ASSERT(eventDispatcher);if (!eventDispatcher-parent()) {eventDispatcher-moveToThread(threadData-thread.loadAcquire());eventDispatcher-setParent(q);}threadData-eventDispatcher eventDispatcher;eventDispatcherReady(); #endif// ... } void QCoreApplicationPrivate::createEventDispatcher() {Q_Q(QCoreApplication);QThreadData *data QThreadData::current();Q_ASSERT(!data-hasEventDispatcher());eventDispatcher data-createEventDispatcher();eventDispatcher-setParent(q); } QAbstractEventDispatcher *QThreadData::createEventDispatcher() {QAbstractEventDispatcher *ed QThreadPrivate::createEventDispatcher(this);eventDispatcher.storeRelease(ed);ed-startingUp();return ed; } QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data) {Q_UNUSED(data); #ifndef Q_OS_WINRTreturn new QEventDispatcherWin32; #elsereturn new QEventDispatcherWinRT; #endif } 2.2 QEventDispatcherWin32的实现 由前面的分析可知在Windows系统下QEventLoop实际上是使用QEventDispatcherWin32来完成消息循环。那QEventDispatcherWin32又是如何实现对Windows消息循环的封装呢 在QEventDispatcherWin32中注册了一个QEventDispatcherWin32_Internal_Widget窗口类 QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext(): atom(0), className(0) {// make sure that multiple Qts can coexist in the same processconst QString qClassName QStringLiteral(QEventDispatcherWin32_Internal_Widget) QString::number(quintptr(qt_internal_proc));className new wchar_t[qClassName.size() 1];qClassName.toWCharArray(className);className[qClassName.size()] 0;WNDCLASS wc;wc.style 0;wc.lpfnWndProc qt_internal_proc;wc.cbClsExtra 0;wc.cbWndExtra 0;wc.hInstance GetModuleHandle(0);wc.hIcon 0;wc.hCursor 0;wc.hbrBackground 0;wc.lpszMenuName NULL;wc.lpszClassName className;atom RegisterClass(wc);if (!atom) {qErrnoWarning(%ls RegisterClass() failed, qUtf16Printable(qClassName));delete [] className;className 0;} } 同时依据该窗口类创建了一个内部窗口 void QEventDispatcherWin32::createInternalHwnd() {Q_D(QEventDispatcherWin32);if (d-internalHwnd)return;d-internalHwnd qt_create_internal_window(this);// setup GetMessage hook needed to drive our posted eventsd-getMessageHook SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());if (Q_UNLIKELY(!d-getMessageHook)) {int errorCode GetLastError();qFatal(Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls,errorCode, qUtf16Printable(qt_error_string(errorCode)));}// start all normal timersfor (int i 0; i d-timerVec.count(); i)d-registerTimer(d-timerVec.at(i)); } static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) {QWindowsMessageWindowClassContext *ctx qWindowsMessageWindowClassContext();if (!ctx-atom)return 0;HWND wnd CreateWindow(ctx-className, // classnamectx-className, // window name0, // style0, 0, 0, 0, // geometryHWND_MESSAGE, // parent0, // menu handleGetModuleHandle(0), // application0); // windows creation data.if (!wnd) {qErrnoWarning(CreateWindow() for QEventDispatcherWin32 internal window failed);return 0;}#ifdef GWLP_USERDATASetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_castLONG_PTR(eventDispatcher)); #elseSetWindowLong(wnd, GWL_USERDATA, reinterpret_castLONG(eventDispatcher)); #endifreturn wnd; } 在QEventDispatcherWin32::processEvents中会不断的调用PeekMessage检查消息队列然后调用TranslateMessage与DispatchMessage进行消息转发。 bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) {Q_D(QEventDispatcherWin32);if (!d-internalHwnd) {createInternalHwnd();wakeUp(); // trigger a call to sendPostedEvents()}d-interrupt.storeRelaxed(false);emit awake();// To prevent livelocks, send posted events once per iteration.// QCoreApplication::sendPostedEvents() takes care about recursions.sendPostedEvents();bool canWait;bool retVal false;do {DWORD waitRet 0;DWORD nCount 0;HANDLE *pHandles nullptr;if (d-winEventNotifierActivatedEvent) {nCount 1;pHandles d-winEventNotifierActivatedEvent;}QVarLengthArrayMSG processedTimers;while (!d-interrupt.loadRelaxed()) {MSG msg;bool haveMessage;if (!(flags QEventLoop::ExcludeUserInputEvents) !d-queuedUserInputEvents.isEmpty()) {// process queued user input eventshaveMessage true;msg d-queuedUserInputEvents.takeFirst();} else if(!(flags QEventLoop::ExcludeSocketNotifiers) !d-queuedSocketEvents.isEmpty()) {// process queued socket eventshaveMessage true;msg d-queuedSocketEvents.takeFirst();} else {haveMessage PeekMessage(msg, 0, 0, 0, PM_REMOVE);if (haveMessage) {if (flags.testFlag(QEventLoop::ExcludeUserInputEvents) isUserInputMessage(msg.message)) {// queue user input events for later processingd-queuedUserInputEvents.append(msg);continue;}if ((flags QEventLoop::ExcludeSocketNotifiers) (msg.message WM_QT_SOCKETNOTIFIER msg.hwnd d-internalHwnd)) {// queue socket events for later processingd-queuedSocketEvents.append(msg);continue;}}}if (!haveMessage) {// no message - check for signalled objectswaitRet MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);if ((haveMessage (waitRet WAIT_OBJECT_0 nCount))) {// a new message has arrived, process itcontinue;}}if (haveMessage) {if (d-internalHwnd msg.hwnd msg.message WM_QT_SENDPOSTEDEVENTS) {// Set result to true, if the message was sent by wakeUp().if (msg.wParam WMWP_QT_FROMWAKEUP)retVal true;continue;}if (msg.message WM_TIMER) {// avoid live-lock by keeping track of the timers weve already sentbool found false;for (int i 0; !found i processedTimers.count(); i) {const MSG processed processedTimers.constData()[i];found (processed.wParam msg.wParam processed.hwnd msg.hwnd processed.lParam msg.lParam);}if (found)continue;processedTimers.append(msg);} else if (msg.message WM_QUIT) {if (QCoreApplication::instance())QCoreApplication::instance()-quit();return false;}if (!filterNativeEvent(QByteArrayLiteral(windows_generic_MSG), msg, 0)) {TranslateMessage(msg);DispatchMessage(msg);}} else if (waitRet - WAIT_OBJECT_0 nCount) {activateEventNotifiers();} else {// nothing todo so breakbreak;}retVal true;}// still nothing - wait for message or signalled objectscanWait (!retVal !d-interrupt.loadRelaxed() (flags QEventLoop::WaitForMoreEvents));if (canWait) {emit aboutToBlock();waitRet MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);emit awake();if (waitRet - WAIT_OBJECT_0 nCount) {activateEventNotifiers();retVal true;}}} while (canWait);return retVal; } 三、总结 依据上述对QEventLoop的实现分析大体上可有以下结论 1. QEventLoop内部实际上是通过QAbstractEventDispatcher子类来完成了消息(事件)分发这实际上就是GoFs Bridge Pattern。 2. QAbstractEventDispatcher定义了事件分发的接口而针对具体窗口系统的实现则有QEventDispatcherWin32、QEventDispatcherWinRT、QEventDispatcherUNIX、QEventDispatcherGlib等负责。 3. 每个线程都有唯一的同一事件分发器线程内的窗体共用同一事件分发器。 4.  在Windows系统下QEventLoop::processEvents函数大体等价于PeekMessage/TranslateMessage/DispatchMessage。 参考文献 Erich Gamma. Design Patterns:elements of reusable object-oriented software. Addison Wesley, 1994. Joseph Ingeno. Handbook of Software Architecture.   参考资料 QEventLoop Get Started with Win32 and C   QAbstractEventDispatcher QThread   QCoreApplication
http://www.pierceye.com/news/622173/

相关文章:

  • 做网站有2个前提条件_一个是网站班级优化大师app下载学生版
  • 自己做网站广告法wordpress自带评论表情
  • 苏州市城乡和建设局网站首页在线crm系统价格
  • php企业门户网站陕西高速公路建设网站
  • 网站商城系统建设方案h5页面制作网站易企秀
  • 绍兴网站建设方案报价seo外贸网站
  • 物流网站建设重要性建筑公司网址大全
  • 腾讯云注册域名后怎么做网站郑州网站建设大华伟业
  • 哪个小说网站可以做封面中国软件园排名前十
  • 门户网站建设预算表十大软件免费下载安装手机版
  • 河南省安阳市建设银行网站wordpress会员卡
  • 旅游类网站怎么做网站前端设计
  • 涉县网站设计商城网站建设推荐
  • 网站注册了域名然后怎么做网站运维是做什么的
  • 深圳学校网站建设哪家好企业宣传网
  • 静态网站如何添加关键词xp花生壳做网站
  • 南宁霸屏网站开发国际数据公司idc
  • 百色建设网站广西建设监理协会网站
  • 天河营销型网站建设惠东网站设计
  • 网站建设用什么科目qq腾讯官网登录入口
  • 做网站硬件手表网站哪个最好知乎
  • 网站制作教程及流程网站优化常见的优化技术
  • 漯河网站建设-千弘网络品划网络做网站
  • 专业广州做网站公司简历网站免费
  • 广州h5网站制作公司营销网站的筛选
  • 国内最新新闻热点事件摘抄seo诊断书
  • 专业的免费网站建设哪家如何优化网站图片
  • 网站开发哪个更专业国家企业信用信息系统(全国)
  • 中小企业网站制作不了国外网站用什么dns
  • word网站的链接怎么做的网页设计大赛网站开发