الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

[ تمت الإجابة ]Global Window Class

مغلق
بدأه C++er في 2 ديسمبر 2009 · 5 رد · 1,615 مشاهدة · في أرشيف قسم Windows APIs
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

المكتبه msftedit.dll عندما يتم تحميلها تقوم بعمل تسجيل لـ window class بإسم RichEdit50W و التى هى احدث اصدار من الأداه RichEdit.

حاولت صنع مثال صغير يقوم بتسجيل Window class من خلال dll فتمت العمليه دون مشاكل و لكن عند استخدام اسم الـ Window class من داخل الـ Process الرئيسى لا يتعرف عليها.

داخل وائق الـ MSDN وجدت ان الـ window class حتى يتم التعامل معها من خلال الـ Process الرئيسى لابد و ان يكون الـ style الخاص بها يحتوى على CS_GLOBALCLASS و لكن و مع استخدمها لم يتم التعرف عليها.

التالى هو مثال الـ DLL

#include <windows.h>

HMODULE hCurModule;

LRESULT CALLBACK CtrlWndProc( HWND, UINT, WPARAM, LPARAM );

VOID RegisterGClass(HMODULE hModule);

BOOL APIENTRY DllMain( HMODULE hModule, DWORD fdwReason, LPVOID lpReserved )
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:

		RegisterGClass(hModule);
		break;

	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:

		UnregisterClass(L"MyTextEdit", hModule);
		break;
	}

	return TRUE;
}

LRESULT CALLBACK CtrlWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	switch(uMsg)
	{
	case WM_CREATE:
		CreateCaret(hWnd,(HBITMAP)NULL, 1, 4);
		break;

	case WM_SETFOCUS:
		ShowCaret(hWnd);
		break;

	case WM_KILLFOCUS:
		DestroyCaret();
		break;

	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
	};	
}

VOID RegisterGClass(HMODULE hModule)
{
	WNDCLASS wc;

	wc.hInstance 	= hModule;
	wc.lpszClassName = L"MyTextEdit";
	wc.style 	= CS_DBLCLKS || CS_GLOBALCLASS;
	wc.lpfnWndProc = CtrlWndProc;
	wc.hCursor 	= (HCURSOR) LoadCursor(hModule,IDC_IBEAM);
	wc.hbrBackground = (HBRUSH)COLOR_BTNFACE;

	wc.cbClsExtra	= NULL;
	wc.cbWndExtra	= NULL;
	wc.hIcon 	= NULL;
	wc.lpszMenuName = NULL;

	hCurModule = hModule;

	RegisterClass(&wc);
}

بالنسبه للبرنامج الذى يتم تحميل الـ dll من خلاله فهو مصنوع بالـ VB.Net و شكله كالتالى

Public Class myctl
	Inherits Control

	Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As IntPtr

	Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
 	Get
 	Dim ptr As IntPtr = LoadLibrary("testCtl.dll")

 	Dim cp As CreateParams = MyBase.CreateParams

 	cp.ClassName = "MyTextEdit"

 	Return cp
 	End Get
	End Property

End Class

و داخل الـ Form_Load استخدم الكود التالى لتجربة الـ WindowClass

Class Form1
	Inherits Form

	Overrides Sub OnLoad(ByVal e As EventArgs)
 	Dim c As New MyCtrl

 	Me.Controls.Add(C)
	End Sub

End Class

عند تشغيل البرنامج يظهر استثناء و الرساله الخاصه به هى "Window class name is not valid."

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

#2

ما بودي أفتي من راسي , كل شي يظهر لي تمام ^^

ما أظن إن هذا سبب المشكلة , لكن برأيي تسجيل الclass الأفضل يكون مرة واحده عند تحميل الdll للعملية , يعني في حدث ال DLL_PROCESS_ATTACH , رح أحاول أسوي dll بلغة purebasic وحاول تجربها عندك =\

الله يوفقك للي فيه الخير ,

#3

قمت بعمل dllبنفس الكود عن طريق Purebasic و يظهر رسالة عند التحميل للعملية تحوي قيمة الatom of the class .

Procedure CtrlWndProc(hWnd.l,uMsg.l,wParam.l,lParam.l)
 Select uMsg
	Case #WM_CREATE
 	CreateCaret_(hWnd,#Null,1,4)
	Case #WM_SETFOCUS
 	ShowCaret_(hWnd)
	Case #WM_KILLFOCUS
 	DestroyCaret_()
	Default
 	ProcedureReturn DefWindowProc_(hwnd,uMsg,wParam,lParam)
 EndSelect
EndProcedure

Procedure RegisterGClass(hModule.l)
 Define.WNDCLASS wc

 wc\hInstance 	= hModule
 wc\lpszClassName = @"MyTextEdit"
 wc\style 	= #CS_DBLCLKS Or #CS_GLOBALCLASS 
 wc\lpfnWndProc	= @CtrlWndProc()
 wc\hCursor 	= LoadCursor_(hModule,#IDC_IBEAM)
 wc\hbrBackground = #COLOR_BTNFACE
 wc\cbClsExtra 	= #Null
 wc\cbWndExtra 	= #Null
 wc\hIcon 	= #Null
 wc\lpszMenuName = #Null

 MessageBox_(hModule,Str(RegisterClass_(@wc)),"testdll",0)

EndProcedure

ProcedureDLL AttachProcess(Instance)
EndProcedure

ProcedureDLL DetachProcess(Instance)
 UnregisterClass_(@"MyTextEdit",Instance)
EndProcedure

RegisterGClass(Instance)

هذا أيضاَ تطبيق exe يقوم بتحميل المكتبة وعمل نافذة وإنشاء الclass السابق , الرسالة الأولى هي رسالة الdll والرسالة الثانية هي رسالة عنوان النافذة من التطبيق نفسه :

LoadLibrary_("testCtl.dll")
OpenWindow(0, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
MessageBox_(0,Str( CreateWindowEx_(0,@"MyTextEdit",@"MyEdit",0,#CW_USEDEFAULT,#CW_USEDEFAULT,250,250,WindowID(0),#Null,GetModuleHandle_(0),#Null)),"App Test",0)
Repeat
 Event = WaitWindowEvent()
 If Event = #PB_Event_CloseWindow
	Quit = 1
 EndIf
Until Quit = 1

End

لا أدري لماذا لم يظهر العنصر الجديد , لست محترفاَ في التعامل مع CreateWindow ومثيلاتها :] لكن وجود مقبض يدل على إنشاء النافذة ,, على ما أظن .___.

سواء إستعملت #CS_GLOBALCLASS أو بدونها , أحصل على Handle للنافذة في البروسس الجديد =\ المشكلة لا يظهر أي كائن , لا أدري ما السبب !! الله يعينك =\ هذا كل ما أقدر عليه ^^

الملفات المترجمة بالمرفقات ,,,

دمت بود ,,

AT2000.rar

تم تعديل هذه المشاركة بواسطة Syntax_err في 3 ديسمبر 2009 في 07:55

1
#5

شكرا لكم

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

#6

عند وضع كود تسجيل الـ window class داخل نفس process فإنها ستكون مرئيه فقط داخل هذا الـ process إن توافر فيها شرط واحد وهو وضع مقبض الـ module داخل hInstance.

لذا ليكون الحل عام : لعمل window class داخل module و استخدامها داخل process لابد من توافر عنصرين و هما :

1 - داخل الـ class style لابد من وجود CS_GLOBALCLASS بالإضافه لأى flags اخرى تريدها.

2 - العنصر hInstance لابدان يكون NULL لإنه ان احتوى على اى قيمه ستكون الـ window class خاصه بهذا الـ module فقط حتى و ان قمت بتطبيق الخطوه 1.

و الله ولى التوفيق

مدونتي: C++ Tips and Tricks

هذا الموضوع مغلق.

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…