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

سلسلة التعامل مع ال Resources

مغلق
بدأه Moudey في 13 مارس 2007 · 3 رد · 1,297 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

الجزء الاول – ايجاد انواع المصادر داخل المكتبة

من خلال هذة السلسلة سنوضح كيفية التعامل مع ملفات المصادر Win32 Resources.

Resources يتم دمجة او حقنة داخل الملف التنفيذي exe او dll ويتكون من صور "Bitmap" او اشكال الماوس "Cursor" او ايقونات "Icon" او بيانات اخري يتم تعريفها من قبل المبرمج وهذة بعض انواع المصادر المعرفة من قبل الويندوز.

 
RT_CURSOR           = 1,      // Hardware-dependent cursor resource. 
RT_BITMAP           = 2,      // Bitmap resource.
RT_ICON             = 3,      // Hardware-dependent icon resource. 
RT_MENU             = 4,      // Menu resource. 
RT_DIALOG           = 5,      // Dialog box. 
RT_STRING           = 6,      // String-table entry.
RT_FONTDIR          = 7,      // Font directory resource. 
RT_FONT             = 8,      // Font resource. 
RT_ACCELERATOR      = 9,      // Accelerator table. 
RT_RCDATA           = 10,     // Application-defined resource (raw data).
RT_MESSAGETABLE     = 11,     // Message-table entry. 
RT_GROUP_CURSOR     = 12,     // Hardware-independent cursor resource. 
RT_GROUP_ICON       = 14,     // Hardware-independent icon resource. 
RT_VERSION          = 16,     // Version resource.
RT_DLGINCLUDE       = 17,     // Allows a resource editing tool to associate a string with an .rc file.
RT_PLUGPLAY         = 19,     // Plug and Play resource. 
RT_VXD              = 20,     // VXD. 
RT_ANICURSOR        = 21,     // Animated cursor. 
RT_ANIICON          = 22,     // Animated icon. 
RT_HTML             = 23,     // HTML. 
RT_MANIFEST         = 24      // Microsoft Windows XP: Side-by-Side Assembly XML Manifest. */

ويتم ايجادالانواع من خلال دوال API والموجودة بمكتبة Kernel32.dll

وفيما يلي عرض الدوال المستخدمة حسب الترتيب.

تقوم هذة الدالة LoadLibraryEx بأيجاد مقبض الملف و تحميلة, ومن ثم نقوم بتحريرها من خلال الدالة FreeLibrary

 
[Flags]
internal enum LoadLibraryFlags
{
      DONT_RESOLVE_DLL_REFERENCES    =  0x00000001,
      LOAD_LIBRARY_AS_DATAFILE       =  0x00000002,
      LOAD_WITH_ALTERED_SEARCH_PATH  =  0x00000008,
      LOAD_IGNORE_CODE_AUTHZ_LEVEL   =  0x00000010
}                  


[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal extern static IntPtr LoadLibraryEx(
      [In] [MarshalAs(UnmanagedType.LPTStr)]string lpLibFileName,
      [In] IntPtr hFile,
      [In] LoadLibraryFlags dwFlags);



[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal extern static bool FreeLibrary(
      [In] IntPtr hModule);

الداله EnumResourceTypes تقم بأرجاع انواع ملفات المصادر المتاحة,

وتحتاج هذة الدالة الي انشاء delegate ليتم ارسال البيانات من خلالها.

 
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal extern static bool EnumResourceTypes(
      [In] IntPtr hModule,
      [In] EnumResTypeProc lpEnumFunc,
      [In] IntPtr lParam);


[return: MarshalAs(UnmanagedType.Bool)]
internal delegate bool EnumResTypeProc(
      [In] IntPtr hModule,
      [In] IntPtr lpszType,
      [In] IntPtr lParam);

مثال علي كيفية ايجاد انواع المصادر

 
// Win32.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

public enum ResourceType : uint
{

      Cursor           = 1,   // RT_CURSOR Hardware-dependent cursor resource. 
      Bitmap           = 2,   // Bitmap resource.
      Icon             = 3,   // Hardware-dependent icon resource. 
      Menu             = 4,   // Menu resource. 
      Dialog           = 5,   // Dialog box. 
      String_Table     = 6,   // String-table entry.
      FontDir          = 7,   // Font directory resource. 
      Font             = 8,   // Font resource. 
      Accelerator      = 9,   // Accelerator table. 
      RC_Data          = 10,  // Application-defined resource (raw data).
      Message_Table    = 11,  // Message-table entry. 
      Group_Cursor     = 12,  // Hardware-independent cursor resource. 
      Group_Icon       = 14,  // Hardware-independent icon resource. 
      Version          = 16,  // Version resource.
      DlgInclude       = 17,  // Allows a resource editing tool to associate a string with an .rc file.
      PlugPlay         = 19,  // Plug and Play resource. 
      VXD              = 20,  // VXD. 
      Animated_Cursor  = 21,  // Animated cursor. 
      Animated_Icon    = 22,  // Animated icon. 
      Html             = 23,  // HTML. 
      Manifest         = 24,  // Microsoft Windows XP: Side-by-Side Assembly XML Manifest.
      Dialog_Data      = 240, //
      ToolBar          = 241  // 
}

[Flags]
internal enum LoadLibraryFlags
{
      DONT_RESOLVE_DLL_REFERENCES         = 0x00000001,
      LOAD_LIBRARY_AS_DATAFILE            = 0x00000002,
      LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008,
      LOAD_IGNORE_CODE_AUTHZ_LEVEL  = 0x00000010
}

public class Win32
{
      #region API Imports

      [return: MarshalAs(UnmanagedType.Bool)]
      internal delegate bool EnumResTypeProc(
            [In] IntPtr hModule,
            [In] IntPtr lpszType,
            [In] IntPtr lParam);


      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
      internal extern static IntPtr LoadLibraryEx(
            [In] [MarshalAs(UnmanagedType.LPTStr)]string lpFileName,
            [In] IntPtr hFile,
            [In] LoadLibraryFlags dwFlags);


      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
      [return: MarshalAs(UnmanagedType.Bool)]
      internal extern static bool FreeLibrary(
            [In] IntPtr hModule);


      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
      [return: MarshalAs(UnmanagedType.Bool)]
      internal extern static bool EnumResourceTypes(
            [In] IntPtr hModule,
            [In] EnumResTypeProc lpEnumFunc,
            [In] IntPtr lParam);

      #endregion


      #region Macro

       // التأكد من نوعية اسم المصدر هل هو من نوع رقمي ام لا
      public static bool IsIntResource(IntPtr value)
      {
            // return (((uint)val) >> 16) == 0;
            return (((uint)value) <= ushort.MaxValue);
      }

      public static bool IsIntResource(string value)
      {
            ushort iResult;
            return ushort.TryParse(value, out iResult);
      }

      public static IntPtr MakeIntResource(ushort wInteger)
      {
            return (IntPtr)wInteger;
      }

      public static int MakeIntResourceW(ushort wInteger)
      {
            return 0x0000FFFF & wInteger;
      }

      public static string GetResourceName(int val)
      {
            return ((ResourceType)val).ToString().Replace('_', ' ');
      }

      public static string GetResourceName(string val)
      {
            if(IsIntResource(val)) {
                  return GetResourceName(int.Parse(val));
            }
            return val;
      }

       // تحويل المؤشر الي نص
      public static string PtrToString(IntPtr ptr)
      {
            return IsIntResource(ptr) ? ptr.ToString() : Marshal.PtrToStringUni(ptr);
      }


      // تحويل int الي مؤشر
      public static IntPtr ToPtr(int val)
      {
            return (IntPtr)((uint)val);
      }

      // تحويل النص الي مؤشر
      public static IntPtr ToPtr(string val)
      {
            if(IsIntResource(val)) {
                  return (IntPtr)uint.Parse(val);
            } else {
                  return Marshal.StringToHGlobalAuto(val);
            }
      }

      #endregion

}

 

// GetResType.cs

using System;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

static class Program
{
            [STAThread]
            static void Main(string[] args)
            {
                  IntPtr hLib = IntPtr.Zero;
                  if(args != null && args.Length> 0) {
                        hLib = Win32.LoadLibraryEx(args[0], IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE);
                        Win32.EnumResourceTypes(hLib, new Win32.EnumResTypeProc(EnumResTypes), IntPtr.Zero);
                  }

                  if(hLib != IntPtr.Zero)
                        Win32.FreeLibrary(hLib);
            }

           static bool EnumResTypes(IntPtr hModule, IntPtr lpszType, IntPtr lParam)
           {
                  if(hModule == IntPtr.Zero)
                        return false;
                  MessageBox.Show(Win32.GetResourceName(Win32.PtrToString(lpszType)));
                  return true;
            }           
}

الجزءالقادم ان شاءالله سأتكلم عن ايجاداسماءالمصادر من خلال انواعها

GetResType.zip

تم تعديل هذه المشاركة بواسطة Moudey في 13 مارس 2007 في 22:34

مواضيع متنوعة

#2

السلام عليكم

مشكور أخي على هذا الكود الجيد.

لقد جربت الكود ولدي إقتراح طبعا إذا سمحت.

حاولت تجربته مع بعض المكتبات ولكنه لا يعمل والمشكل في الدالةEnumResourceTypes إذ أنها "تفشل" أحيانا لذلك غيرت الكود بالشكل التالي:

private void btnGetLib_Click(object sender, EventArgs e)
 {
   bool enumerated;
   IntPtr hLib = IntPtr.Zero;
	if(ofd.ShowDialog() == DialogResult.OK) 
		{
		 txtLibPath.Text = ofd.FileName;
		treeRes.Nodes.Clear();
		// ÇíÌÇÏ ãÞÈÖ ÇáãáÝ æÊÍãíáÉ

		hLib = Win32.LoadLibraryEx(ofd.FileName, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE);

		enumerated = Win32.EnumResourceTypes(hLib, new Win32.EnumResTypeProc(EnumResTypes), IntPtr.Zero);
		if (!enumerated)
		 {
		  if (Win32.GetLastError() == 193)
		   { textBox1.Text = "193 - ERROR_BAD_EXE_FORMAT (" + ofd.FileName + " is not a valid application.)"; }
		  else
		   textBox1.Text = "Error :" + Win32.GetLastError().ToString(); 
			}
		}
	if(hLib != IntPtr.Zero)
		Win32.FreeLibrary(hLib);

}

والله أعلم

post-91400-1173975167_thumb.jpg

#3

عذرا نسيت تعريف الدالة GetLastError

   [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false,
		ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
		internal static extern Int32 GetLastError();
#4

السلام عليكم,

شكراً اخي الكريم Ben_Laiid علي تفاعلك وتنقيح الكود ايضاً.

بالنسبة للاجراء GetLastError اعتقد انة لاداعي للتصريح عنة فأنة موجود في كلاس System.Runtime.InteropServices.Marshal.GetLastWin32Error

-----------------------------

نكمل ان شاءالله هذا الموضوع.

في الجزء السابق عرفنا كيف نسطيع جلب انواع المصادر الموجود في التطبيق,

ومن خلال ذلك نسطيع جلب جميع اسماء عناصر تلك المصادر مع جلب اللغات المتاحة مع كل عنصر

MENU  <- النوع           
	1  <- العنصر          
	   1033 <- اللغة    
	   1049
	   1029

ولجلب عناصر المصادر نحتاج الي اجراء من المكتبة kernel32.dll بأسم EnumResourceNames وتحتاج الي انشاء delegate ليتم ارسال اسماء العناصر من خلالها.

[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal extern static bool EnumResourceNames(
	[In] IntPtr hModule,   // مقبض الملف
	[In] IntPtr lpszType,  // نوع المصدر المراد جلب عناصرة
	[In] EnumResName lpEnumFunc, // EnumResNameارسال البيانات الي 
	[In] IntPtr lParam);


[return: MarshalAs(UnmanagedType.Bool)]
internal delegate bool EnumResName (
	[In] IntPtr hModule,    // مقيض الملف
	[In] IntPtr lpszType,   // نوع المصدر
	[In] IntPtr lpszName,   // اسم العنصر
	[In] IntPtr lParam);

ولجلب لغات كل عنصر نحتاج الي الاجراء التالي من نفس الكتبة السابقة وتحت اسم EnumResourceLanguages وتحتاج الي انشاء delegate ليتم ارسال لغة كل عناصر من خلالها.

[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal extern static bool EnumResourceLanguages(
	[In] IntPtr hModule,    // مقبض الملف
	[In] IntPtr lpszType,   // نوع المصدر
	[In] IntPtr lpName,     // اسم العنصر
	[In] EnumResLang lpEnumFunc, 
	[In] IntPtr lParam);

[return: MarshalAs(UnmanagedType.Bool)]
internal delegate bool EnumResLang (
	[In] IntPtr hModule,   // مقبض الملف
	[In] IntPtr lpszType,  // نوع المصدر
	[In] IntPtr lpszName,  // اسم العنصر
	[In] ushort wIDLanguage, // لغة العنصر
	[In] IntPtr lParam);

وهذا المثال يوضح كيفية جلب جميع انواع المصادر مع جلب عناصرها مع جلب جميع اللغات المتاحة في كل عنصر.

وهو تطوير للمثال السابق.

public partial class frmMain : Form
{
	int tCount, nCount;

	// اجراء جلب انواع المصادر
	private bool EnumResTypes(
		IntPtr hModule, IntPtr lpszType, IntPtr lParam)
	{
		tCount = nCount = 0;
		string type = Win32.PtrToString(lpszType);
		// إضافة نوع المصدر الي الشجرة
		treeRes.Nodes.Add(type, Win32.GetResourceName(type));
		tCount = treeRes.Nodes.Count - 1;

		return Win32.EnumResourceNames(
			hModule, lpszType, new Win32.EnumResNameProc(EnumResNames), IntPtr.Zero);
	}

	// اجراء جلب اسماء العناصر المتاحة ضمن انواع المصادر
	private bool EnumResNames(
		IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam)
	{
		string name = Win32.PtrToString(lpszName);
		// إضافة العنصر الي الشجرة داخل النوع المنتمي لية
		treeRes.Nodes[tCount].Nodes.Add(name, name);
		nCount = treeRes.Nodes[tCount].Nodes.Count - 1;

		return Win32.EnumResourceLanguages(
			hModule, lpszType, lpszName, new Win32.EnumResLangProc(EnumResLang), IntPtr.Zero);
	}

	// اجراء جلب اللغات المتوفرة في كل عنصر
	private bool EnumResLang(
		IntPtr hModule, IntPtr lpszType, IntPtr lpszName, ushort wIDLanguage, IntPtr lParam)
	{
		// إضافة لغة العنصر الي الشجرة 
		treeRes.Nodes[tCount].Nodes[nCount].Nodes.Add(wIDLanguage.ToString());
		return true;
	}

	private void btnGetLib_Click(object sender, EventArgs e)
	{
		IntPtr hLib = IntPtr.Zero;
		if(dlgOpen.ShowDialog() == DialogResult.OK) {

			txtLibPath.Text = dlgOpen.FileName;
			treeRes.Nodes.Clear();
			// تحميل الملف
			hLib = Win32.LoadLibraryEx(
				dlgOpen.FileName, IntPtr.Zero, LoadLibraryFlags.Load_Library_As_DataFile);
			// التحقق من ان الملف انة ملف تنفيذي ام لا
			if(hLib == IntPtr.Zero) {
				if(Marshal.GetLastWin32Error() == 193)
					MessageBox.Show(
						"193 - ERROR_BAD_EXE_FORMAT (\"" + dlgOpen.FileName + 
						"\" is not a valid application.)", "Error");
				else
					MessageBox.Show(
						"Error : " + Marshal.GetLastWin32Error().ToString(), "Error");

				return;
			}
			// إيجاد او جلب انواع المصادر المتوفرة في التطبيق
			Win32.EnumResourceTypes(
				hLib, new Win32.EnumResTypeProc(EnumResTypes), IntPtr.Zero);
		}

		if(hLib != IntPtr.Zero)
			Win32.FreeLibrary(hLib);

	}

	public frmMain()
	{
		InitializeComponent();
	}
}

GetResType.zip

مواضيع متنوعة

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

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