يقوم MFC بتغليف العديد من عناصر التحكم شائعة الاستخدام وتغليف أسماء الفئات دون توفير واجهة واضحة. لكتابة برنامج نافذة باستخدام win api، فإن الخطوة الأولى هي تسجيل فئة النافذة.
في هذا الوقت، يتم تسجيل اسم الفئة واسم العنوان معًا، لذلك يمكن للمستخدم تعيين العنوان بسهولة. ولسوء الحظ، قد يكون السبب هو اسم النافذة يمكن تغييرها بشكل مستمر، ولكن لا يمكن تغيير اسم الفئة. يتم تحديد اسم فئة النافذة بواسطة "إنشاء". قبل الإنشاء، تحتاج إلى تحديد اسم فئة نافذة مسجلة للنافذة كمعلمة، وسوف يتم إنشاء النافذة في النهاية إلى CreateEx في CreateEx أكثر وضوحا
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam /* = NULL */){ return CreateEx(dwExStyle, lpszClassName, lpszWin الاسم السفلي, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), (HMENU)(UINT_PTR)nID, lpParam);}BOOL CWnd::CreateEx(DWORD) dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam){ ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClass الاسم) ||. lpszClassName )); ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName)); // السماح بتعديل العديد من معلمات الإنشاء الشائعة CREATESTRUCT cs; ؛ خدمات العملاء. style = cs.x = x; cs.y = y; cs.cy = nHeight; ) { PostNcDestroy(); return FALSE; } AfxHookWindowCreate(this); cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);#ifdef _DEBUG if (hWnd == NULL) { TRACE(traceAppMsg, 0, "تحذير: فشل إنشاء النافذة: يقوم GetLastError بإرجاع 0x%8.8 Xn", GetLastError()); }#endif if (!AfxUnhookWindowCreate()) PostNcDestroy(); // التنظيف إذا فشل CreateWindowEx في وقت مبكر جدًا if (hWnd == NULL) return FALSE; ASSERT(hWnd == m_hWnd); // يجب أن يتم ضبطه في خطاف إرسال الرسائل return TRUE;}
يمكنك أن ترى أنه وصل أخيرًا إلى::AfxCtxCreateWindowEx. يمكنك بسهولة معرفة أنه يتم استدعاء CreateWindowEx هنا لإنشاء نافذة.
يوجد PreCreateWindow(cs) في المقدمة، وبعد معالجة cs بواسطة PreCreateWindow، يتم تسليمه إلى ::AfxCtxCreateWindowEx للمعالجة
:: يتم نقل AfxCtxCreateWindowEx إلى CreateWindowEx. cs.lpszClass هو اسم الفئة، مما يوضح أن AfxCtxCreateWindowEx لديه نوايا حسنة.
يمكننا زيادة تحميل PreCreateWindow لتعديل اسم الفئة، كما يلي:
// TODO: أضف كودًا متخصصًا هنا و/أو اتصل بالفئة الأساسية //VERIFY(AfxDeferRegisterClass(AFX_WND_REG)); //AfxEndDeferRegisterClass(AFX_WND_REG); //cs.lpszClass = AfxRegisterWndClass(NULL); 0, sizeof(WNDCLASS)); // ابدأ بـ NULL // defaults wndcls.style = CS_DBLCLKS |.CS_HREDRAW |. // يمكنك تحديد إجراء النافذة الخاصة بك wndcls.lpfnWndProc = ::DefWindowProc; ; wndcls.hIcon = NULL; // أو قم بتحميل رمز مختلف wndcls.hCursor =NULL; wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wndcls.lpszMenuName = NULL; wndcls.lpszClassName = _T("MyNewClass"); // قم بتسجيل الفصل الجديد والخروج إذا فشل if(!AfxRegisterClass(&wndcls)) { TRACE("فشل تسجيل الفصلn"); } cs.lpszClass = wndcls.lpszClassName; return TRUE;
في الواقع، يتم تمرير سلسلة اسم فئة مسجلة إلى CreateWindowEx. انطلاقًا من التعليقات الواردة في الكود أعلاه، استخدمت أيضًا AfxRegisterWndClass، وهي طريقة تسمح للنظام بإنشاء className. CWnd::PreCreateWindow لا يناسب رغباتي، لذلك علقت عليه في الواقع، لا يوجد شيء فيه، إنه مجرد حكم. في MFC، الفئات الأخرى المشتقة من CWnd ليست بهذه البساطة، ومع ذلك، فإن تعديل اسم الفئة والتحميل الزائد لهذه الطريقة سيكون في الغالب أمرًا جيدًا.
نعم، يمكن لمعظمهم القيام بذلك، ولسوء الحظ، لا تعمل هذه الطريقة مع Dialog، لأنها لا تستخدم CWnd::Create، لذلك لا يمكن التحايل عليها.
PreCreateWindow قادم. لا يمكن كسر هذه الطريقة في مربع الحوار. لأنه يمكن إنشاء CDialog مباشرة باستخدام واجهة برمجة التطبيقات (API) الخاصة بالنظام، وليست هناك حاجة إلى إزعاج CWnd للنقل إلى CReateWindowEx، لذلك لا يمكنك استخدام الطريقة المذكورة أعلاه لتغيير اسم الفئة في مربع الحوار.
ألق نظرة على رمز الإنشاء الخاص به:
BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd){ ASSERT(IS_INTRESOURCE(lpszTemplateName) || AfxIsValidString(lpszTemplateName)); m_lpszTemplateName // يستخدم للمساعدة if (IS_INTRESOURCE(m_lpszTemplateN آمي) && m_nID مساعدة == 0) m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);#ifdef _DEBUG if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE)) { ASSERT(FALSE); // اسم قالب الحوار غير صالح PostNcDestroy(); } #endif //_DEBUG HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG); ، hInst ) ; FreeResource(hTemplate);
يمكن ملاحظة أن CDialog يتم إنشاؤه بواسطة الموارد، ويمكن القيام بذلك بهذه الطريقة من خلال تحديد "اسم فئة الحوار" للفئة في البرنامج النصي للمورد. قم بتسجيل اسم الفئة هذا قبل إنشاء domodal، ثم انتظر حتى يتم إنشاء ملف هذا كل شيء.
خلال هذه الفترة، كنت مشغولاً بجوانب أخرى، ونسيت الكثير عن آلية تعبئة MFC، وسأقوم بتتبع الكود لتجديد المعلومات.