سئوال درباره ی API های ویندوز

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
استاد علی ، در قضیه ی استفاده از تابع api برای فونت ، در استراکچر CHOOSEFONT ، فیلدی بنام lpTemplateName و lpszStyle دارن که به ترتیب از نوع های LPCTSTR و LPTSTR هستن که کلا رشته هستن ولی برخلاف فیلد lfFaceName در استراکچر CHOOSEFONT که از نوع TCHAR و کلا رشته هست و در فیلد lfFaceName ، گفت که 32 بایت لازم داره ؛ ولی در فیلدهای lpTemplateName و lpszStyle نگفت . در اینجا باید چند بایت براشون فضا بگیریم؟ و از کجا باید متوجه بشیم چند بایت بگیریم؟ آخه گفتین که 1 بایت کم و زیاد شدن برای استراکچر ، خطا میده
دوم اینکه هر جا نوع کاراکتر ، ansi بخواد (8 بیت) ولی ما نوع کاراکتر رو ascii بدیم (7 بیت) ، برای نام فونت (و هر چیزی که اسم میخواد) ، اشکال داره؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
من که قاتی کردم
کد زیر رو نوشتم ولی تا حالا که دیالوگ فونت بالا میومد ، همین قدر هم دیگه بالا نمیاد! :


کد:
 _LogFont = Memory.CreateStructure("long, long, long, long, long, byte, byte, byte, byte, byte, byte, byte, byte, char[32]");  -- ÇÓÊÑǘÑ ãÑÈæØ Èå ÇØáÇÚÇÊ LOGFONT
Memory.SetStructureData(_LogFont, 1, 0, 0, ""); -- lfHeight
Memory.SetStructureData(_LogFont, 2, 0, 0, ""); -- lfWidth
Memory.SetStructureData(_LogFont, 3, 0, 0, ""); -- lfEscapement
Memory.SetStructureData(_LogFont, 4, 0, 0, ""); -- lfOrientation
Memory.SetStructureData(_LogFont, 5, 0, 400, ""); -- lfWeight
Memory.SetStructureData(_LogFont, 6, 0, 1, ""); --Italic
Memory.SetStructureData(_LogFont, 7, 0, 1, "");  --Underline
Memory.SetStructureData(_LogFont, 8, 0, 1, "");  --StrikeOut
Memory.SetStructureData(_LogFont, 9, 0, 0, "");  --Ansi_CHARSET
Memory.SetStructureData(_LogFont, 10, 0, "OUT_TT_PRECIS", "");  --OutPrecision
Memory.SetStructureData(_LogFont, 11, 0, "CLIP_DEFAULT_PRECIS", "");   --ClipPrecision
Memory.SetStructureData(_LogFont, 12, 0, 4, "");    --FontQuality
Memory.SetStructureData(_LogFont, 13, 0, 1, "");    --PitchAndFamily  FIXED_PITCH
  Memory.SetStructureData(_LogFont, 14, 1, 73, "");    --FaceName  chaharomin arguman , code ascii hast . reshteh "Impact"
  Memory.SetStructureData(_LogFont, 14, 2, 109, "");    --FaceName
  Memory.SetStructureData(_LogFont, 14, 3, 112, "");    --FaceName
  Memory.SetStructureData(_LogFont, 14, 4, 97, "");    --FaceName
  Memory.SetStructureData(_LogFont, 14, 5, 99, "");    --FaceName
  Memory.SetStructureData(_LogFont, 14, 6, 116, "");    --FaceName

chooseFont = Memory.CreateStructure("long, long, long, long, long, long, long, long, long, long, long, long, short, long, long");  -- ÇÓÊÑǘÑí ˜å ãÑÈæØ Èå ÇØáÇÚÇÊÇÓÊÑǘÑ CHOOSEFONT åÓÊ
Memory.SetStructureData(chooseFont, 1, 0, Memory.Size(chooseFont), "");  -- lStructSize
Memory.SetStructureData(chooseFont, 2, 0, Application.GetWndHandle(), "");  -- hwndOwner
Memory.SetStructureData(chooseFont, 4, 0, _LogFont, "");  -- lpLogFont
Memory.SetStructureData(chooseFont, 5, 0, 0x00000100, "");  -- iPointSize
Memory.SetStructureData(chooseFont, 6, 0, 0x02030041, "");   --Flags  CF_SCREENFONTS | CF_FORCEFONTEXIST | CF_INACTIVEFONTS | CF_INITTOLOGFONTSTRUCT | CF_SCALABLEONLY
Memory.SetStructureData(chooseFont, 7, 0, "255", "");  -- rgbColors
Memory.SetStructureData(chooseFont, 8, 0, "", "");  -- lCustData
Memory.SetStructureData(chooseFont, 9, 0, "", "");  -- lpfnHook
Memory.SetStructureData(chooseFont, 10, 0, "", "");  -- lpTemplateName string
Memory.SetStructureData(chooseFont, 11, 0, "", "");  -- hInstance
Memory.SetStructureData(chooseFont, 12, 0, "", "");  -- lpszStyle string
Memory.SetStructureData(chooseFont, 13, 0, 0x0100, "");  --nFontType  BOLD_FONTTYPE
Memory.SetStructureData(chooseFont, 14, 0, 64, "");  -- nSizeMin
Memory.SetStructureData(chooseFont, 15, 0, 64, "");  -- nSizeMax
local isOkSelect = DLL.CallFunction("comdlg32.dll", "ChooseFontA", chooseFont, DLL_RETURN_TYPE_LONG, DLL_CALL_STDCALL);  -- ÝÑÇÎæäí ÊÇÈÚ ChooseFont ˜å ÏÑ ÝÇíá Comdlg32.dll åÓÊ

if (tonumber(isOkSelect) == 1) then  -- ÇÑ ˜ÇÑÈÑ ok ÑÇ ÇäÊÎÇÈ ˜ÑÏ
    --result = Subclass.Create(Application.GetWndHandle());


     fPtr = Memory.GetStructureData(_LogFont, 14, 0, "");  -- ÇØáÇÚÇÊ ÐÎíÑå ÔÏå ÏÑ åÇÑÏåãíä ÇÓÊÑǘÑ ÇÓÊÑǘÑ _LogFont Ñæ ȐíÑ
    Dialog.Message("Notice", fPtr, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
end

نمیدونم چرا با کد زیر بالا میاد ولی با کد بالا نه ! :


کد:
local _LogFont = Memory.CreateStructure("long, long, long, long, long, long, long, long, long, long, long, long, long, long");
Memory.SetStructureData(_LogFont, 1, 0, "<0", "");
Memory.SetStructureData(_LogFont, 2, 0, "0", "");
Memory.SetStructureData(_LogFont, 3, 0, "20", "");
Memory.SetStructureData(_LogFont, 4, 0, "20", "");
Memory.SetStructureData(_LogFont, 5, 0, "400", "");
Memory.SetStructureData(_LogFont, 6, 0, true, ""); --Italic
Memory.SetStructureData(_LogFont, 7, 0, true, "");  --Underline
Memory.SetStructureData(_LogFont, 8, 0, true, "");  --StrikeOut
Memory.SetStructureData(_LogFont, 9, 0, "0xB2", "");  --ARABIC_CHARSET
Memory.SetStructureData(_LogFont, 10, 0, "OUT_TT_PRECIS", "");  --OutPrecision
Memory.SetStructureData(_LogFont, 11, 0, "CLIP_DEFAULT_PRECIS", "");   --ClipPrecision
Memory.SetStructureData(_LogFont, 12, 0, "0x04", "");    --FontQuality
Memory.SetStructureData(_LogFont, 13, 0, "1", "");    --PitchAndFamily  FIXED_PITCH

Memory.SetStructureData(_LogFont, 14, 0, "Arial", "");    --FaceName

local str = Memory.CreateStructure("long, long, long, long, long, long, long, long, long, long, long, long, long, long, long");

Memory.SetStructureData(str, 1, 0, Memory.Size(str), "");
Memory.SetStructureData(str, 2, 0, Application.GetWndHandle(), "");
Memory.SetStructureData(str, 4, 0, _LogFont, "");
Memory.SetStructureData(str, 5, 0, "0x00000100", "");
Memory.SetStructureData(str, 6, 0, "0x00000100", "");   --Flags
Memory.SetStructureData(str, 7, 0, "255", "");
Memory.SetStructureData(str, 8, 0, "", "");
Memory.SetStructureData(str, 9, 0, "", "");
Memory.SetStructureData(str, 10, 0, "", "");
Memory.SetStructureData(str, 11, 0, "", "");
Memory.SetStructureData(str, 12, 0, "", "");
Memory.SetStructureData(str, 13, 0, "0x0100", "");  --BOLD_FONTTYPE
Memory.SetStructureData(str, 14, 0, 6, "");
local result = DLL.CallFunction("comdlg32.dll", "ChooseFontA", str, DLL_RETURN_TYPE_LONG, DLL_CALL_STDCALL);

if result~=false then
     _c = Memory.GetStructureData(str, 5, 0, "");  --  _GetFontSize

     Dialog.Message("", _c);
end
Memory.FreeStructure(_LogFont);
Memory.FreeStructure(str);
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام مجدد
کدش رو فهمیدم یعنی مقدار بازگشتی نام رشته رو درست برمیگردونه


کد:
local _LogFont = Memory.CreateStructure("long, long, long, long, long, byte, byte, byte, byte, byte, byte, byte, byte, char[32]");
Memory.SetStructureData(_LogFont, 1, 0, "<0", "");
Memory.SetStructureData(_LogFont, 2, 0, "0", "");
Memory.SetStructureData(_LogFont, 3, 0, "20", "");
Memory.SetStructureData(_LogFont, 4, 0, "20", "");
Memory.SetStructureData(_LogFont, 5, 0, "400", "");
Memory.SetStructureData(_LogFont, 6, 0, true, ""); --Italic
Memory.SetStructureData(_LogFont, 7, 0, true, "");  --Underline
Memory.SetStructureData(_LogFont, 8, 0, true, "");  --StrikeOut
Memory.SetStructureData(_LogFont, 9, 0, "0xB2", "");  --ARABIC_CHARSET
Memory.SetStructureData(_LogFont, 10, 0, "OUT_TT_PRECIS", "");  --OutPrecision
Memory.SetStructureData(_LogFont, 11, 0, "CLIP_DEFAULT_PRECIS", "");   --ClipPrecision
Memory.SetStructureData(_LogFont, 12, 0, "0x04", "");    --FontQuality
Memory.SetStructureData(_LogFont, 13, 0, "1", "");    --PitchAndFamily  FIXED_PITCH

     Memory.SetStructureData(_LogFont, 14, 1, 73, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 2, 109, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 3, 112, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 4, 97, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 5, 99, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 6, 116, "");    --FaceName "Impact"


local str = Memory.CreateStructure("long, long, long, long, long, long, long, long, long, long, long, long, long, long, long");
Memory.SetStructureData(str, 1, 0, Memory.Size(str), "");
Memory.SetStructureData(str, 2, 0, Application.GetWndHandle(), "");
Memory.SetStructureData(str, 4, 0, _LogFont, "");
Memory.SetStructureData(str, 5, 0, "0x00000100", "");
Memory.SetStructureData(str, 6, 0, "0x00000100", "");   --Flags
Memory.SetStructureData(str, 7, 0, "255", "");
Memory.SetStructureData(str, 8, 0, "", "");
Memory.SetStructureData(str, 9, 0, "", "");
Memory.SetStructureData(str, 10, 0, "", "");
Memory.SetStructureData(str, 11, 0, "", "");
Memory.SetStructureData(str, 12, 0, "", "");
Memory.SetStructureData(str, 13, 0, "0x0100", "");  --BOLD_FONTTYPE
Memory.SetStructureData(str, 14, 0, 6, "");
local isOkSelect = DLL.CallFunction("comdlg32.dll", "ChooseFontA", str, DLL_RETURN_TYPE_LONG, DLL_CALL_STDCALL);  -- فراخوني تابع ChooseFont که در فايل Comdlg32.dll هست

if (tonumber(isOkSelect) == 1) then
    myString = Memory.GetString(_LogFont + 28, -1, "Ascii");
  
     fPtr = Memory.GetStructureData(_LogFont, 14, 1, "");  -- اطلاعات ذخيره شده در چهاردهمين استراکچر استراکچر _LogFont رو بگير
    Dialog.Message("Notice", myString, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
end

ولی کد اسکی رشته ی "Impact" رو بصورت پیش فرض که بهش میدم ، اولا با کد بالا ، فقط 3 حرف آخرش رو برمیگردونه یعنی "act" رو برمیگردونه و در صفحه ی دیالوگ فونت ، بصورت پیش فرض فونتی با نام "Impact رو انتخاب نمیکنه . دوما که کاراکترها رو که به اندازه ی 4 کاراکتر جلوتر مینویسم یعنی قسمتی از کد بالا رو به شکل زیر تغییر میدم :


کد:
     Memory.SetStructureData(_LogFont, 14, 4, 73, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 5, 109, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 6, 112, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 7, 97, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 8, 99, "");    --FaceName "Impact"
      Memory.SetStructureData(_LogFont, 14, 9, 116, "");    --FaceName "Impact"
     myString = Memory.GetString(_LogFont + 28, -1, "Ascii");
    Dialog.Message("Notice", myString, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);

این بار ، استعلامش درسته یعنی در کد ، رشته ی "Impact" رو چاپ میکنه ولی باز هم در صفحه ی دیالوگ فونت ، بصورت پیش فرض فونتی با نام "Impact رو انتخاب نمیکنه .
چرا؟!! نمیدونم
 

the_king

مدیرکل انجمن
سلام
استاد علی ، در قضیه ی استفاده از تابع api برای فونت ، در استراکچر CHOOSEFONT ، فیلدی بنام lpTemplateName و lpszStyle دارن که به ترتیب از نوع های LPCTSTR و LPTSTR هستن که کلا رشته هستن ولی برخلاف فیلد lfFaceName در استراکچر CHOOSEFONT که از نوع TCHAR و کلا رشته هست و در فیلد lfFaceName ، گفت که 32 بایت لازم داره ؛ ولی در فیلدهای lpTemplateName و lpszStyle نگفت . در اینجا باید چند بایت براشون فضا بگیریم؟ و از کجا باید متوجه بشیم چند بایت بگیریم؟ آخه گفتین که 1 بایت کم و زیاد شدن برای استراکچر ، خطا میده
شما ساختار CHOOSEFONT رو که تجربی کشف نمی کنین، به مستنداتش تو MSDN رجوع می کنین. یکبار این دو تا ساختار رو در MSDN ببینید بعد بینید جای ابهام داره یا نه. که وقتی اینکار رو بکنین می بینین تعریف lpTemplateName و lpszStyle شباهتی به lfFaceName نداره که بهم ربطش می دید. نوع داده شون شبیه هم نیست که طول براش مشخص کنه، تو MSDN ببینید دو تا structure رو، اون یه آرایه با طول ثابت بود، lpTemplateName و lpszStyle اشاره گر به رشته است، اشاره گر به رشته مگه طول رشته لازم داره که بگه چند کاراکتر باشه یا روی طول حافظه struct تاثیر بذاره؟ طول اشاره گر مشخص و ثابته، یا 32 بیتی ئه، یا 64 بیتی. برنامه تون در مود x86 اجرا بشه 4 بایته، در مود x64 اجرا بشه 8 بایته که اینم به این بستگی داره که برنامه تون 32 بیتی باشه یا 64 بیتی.
lpTemplateName هم کلا مقداریه که ورودیه، شما تعیین اش می کنید، طول رشته اش رو هم به رشته ای که میدید بستگی داره، خروجی نداره که بگیم طول بافر چقدر باشه که جا بشه.
برای طول lpszStyle هم مایکروسافت نمی تونه طول متعارف یا حداقل یا حداکثر مشخصه کنه، در هر موردی که میشده همچین چیزی تعیین بشه توصیه کرده که بافر حداقل برای فلان تعداد کاراکتر جا داشته باشه. این دیگه بستگی به طراح فونت داره، هر فونتی و با هر زبانی ممکنه طول Style متفاوتی داشته باشه. استفاده ازش رو هم توصیه نکرده چون مقادیر استاندارد نیست، طراح فونت میتونه هر اسم style ای رو برای فونت اش ثبت کنه. بالاخره اون ساختار CHOOSEFONT با Windows 95 ئه 1995 هم استفاده میشده، نمیتونیم بگیم این همه سال ازش برنامه نویس ها استفاده می کنند ولی مستنداتش ناقصه و کامل توضیح داده نشده.
دوم اینکه هر جا نوع کاراکتر ، ansi بخواد (8 بیت) ولی ما نوع کاراکتر رو ascii بدیم (7 بیت) ، برای نام فونت (و هر چیزی که اسم میخواد) ، اشکال داره؟
بله، برای اسامی که کاراکتر خارج از محدوده Character Set دارند ایراد داره، اما کلا در سیستم عاملی که Unicode ئه و با رشته های Unicode سر و کار داره خود ANSI ئه 8 بیتی با هر Character Set ای که باشه مشکل سازه.
با مسیر فایل و فولدر مشکل دارند، با اسامی فونت مشکل دارند، با اسامی فیلد های پایگاه داده و مرتب سازی رشته ها و کاراکتر های کنترلی متن و پاراگراف بندی و ...
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
شما ساختار CHOOSEFONT رو که تجربی کشف نمی کنین، به مستنداتش تو MSDN رجوع می کنین. یکبار این دو تا ساختار رو در MSDN ببینید بعد بینید جای ابهام داره یا نه. که وقتی اینکار رو بکنین می بینین تعریف lpTemplateName و lpszStyle شباهتی به lfFaceName نداره که بهم ربطش می دید. نوع داده شون شبیه هم نیست که طول براش مشخص کنه، تو MSDN ببینید دو تا structure رو، اون یه آرایه با طول ثابت بود، lpTemplateName و lpszStyle اشاره گر به رشته است، اشاره گر به رشته مگه طول رشته لازم داره که بگه چند کاراکتر باشه یا روی طول حافظه struct تاثیر بذاره؟ طول اشاره گر مشخص و ثابته، یا 32 بیتی ئه، یا 64 بیتی. برنامه تون در مود x86 اجرا بشه 4 بایته، در مود x64 اجرا بشه 8 بایته که اینم به این بستگی داره که برنامه تون 32 بیتی باشه یا 64 بیتی.
lpTemplateName هم کلا مقداریه که ورودیه، شما تعیین اش می کنید، طول رشته اش رو هم به رشته ای که میدید بستگی داره، خروجی نداره که بگیم طول بافر چقدر باشه که جا بشه.
برای طول lpszStyle هم مایکروسافت نمی تونه طول متعارف یا حداقل یا حداکثر مشخصه کنه، در هر موردی که میشده همچین چیزی تعیین بشه توصیه کرده که بافر حداقل برای فلان تعداد کاراکتر جا داشته باشه. این دیگه بستگی به طراح فونت داره، هر فونتی و با هر زبانی ممکنه طول Style متفاوتی داشته باشه. استفاده ازش رو هم توصیه نکرده چون مقادیر استاندارد نیست، طراح فونت میتونه هر اسم style ای رو برای فونت اش ثبت کنه. بالاخره اون ساختار CHOOSEFONT با Windows 95 ئه 1995 هم استفاده میشده، نمیتونیم بگیم این همه سال ازش برنامه نویس ها استفاده می کنند ولی مستنداتش ناقصه و کامل توضیح داده نشده.

بله، برای اسامی که کاراکتر خارج از محدوده Character Set دارند ایراد داره، اما کلا در سیستم عاملی که Unicode ئه و با رشته های Unicode سر و کار داره خود ANSI ئه 8 بیتی با هر Character Set ای که باشه مشکل سازه.
با مسیر فایل و فولدر مشکل دارند، با اسامی فونت مشکل دارند، با اسامی فیلد های پایگاه داده و مرتب سازی رشته ها و کاراکتر های کنترلی متن و پاراگراف بندی و ...

آها
ممنون استاد علی
پس هر جا نوعش نوشته LPCTSTR و LPTSTR که مخفف Long Point T String (حالا کلا دقیقا همه ی کلماتش رو نمیدونم:green:) ، چون گفته Point پس منظورش اینه که اشاره گر به رشته میخواد و چون اشاره گره ، طول رشته رو هر چقدر که دلمون خواست میتونیم بذاریم . درسته؟
و معمولا هر جای دیگه ای که نوع TCHAR بخواد ، اولا چون نوع Char رو خواست و نگفت که اشاره گر میخواد ، پس نباید اشاره گر بهش بدیم بلکه باید آرایه ای از کاراکترها بهش بدیم . درسته؟

درباره ی ansi و unicode هم اگه کد اسکی حروف ، از 127 بیشتر نشه که مشکلی پیش نمیاد دیگه؟
 

the_king

مدیرکل انجمن
آها
ممنون استاد علی
پس هر جا نوعش نوشته LPCTSTR و LPTSTR که مخفف Long Point T String (حالا کلا دقیقا همه ی کلماتش رو نمیدونم:green:) ، چون گفته Point پس منظورش اینه که اشاره گر به رشته میخواد و چون اشاره گره ، طول رشته رو هر چقدر که دلمون خواست میتونیم بذاریم . درسته؟
و معمولا هر جای دیگه ای که نوع TCHAR بخواد ، اولا چون نوع Char رو خواست و نگفت که اشاره گر میخواد ، پس نباید اشاره گر بهش بدیم بلکه باید آرایه ای از کاراکترها بهش بدیم . درسته؟

طول رشته رو ممکنه هر چقدر دلتون بخواد نتونید بذارید ولی به هر حال اولا طولش متغیر ئه و ثانیا فقط اشاره گر اش جزئی از ساختار ئه.
آرایه با طول ثابت مقدار مشخصی برای طول داره، دیگه از این مشخص تر نمیتونه تعریفی باشه که بگید چطوری تفاوت اش رو تشخیص بدیم. TCHAR نباشه، بایت باشه، WORD باشه، WCHAR باشه، اون قسمتش مهم نیست، مهم اینه که بعد اسم متغیر [size] ای در کار باشه که size مشخص کننده طول آرایه است.
طبق تعاریف سیستم عامل معمولا تعاریفی که با LP و P شروع بشه یعنی اشاره گر ئه، C داشته باشه یعنی ANSI ئه، W داشته باشه یعنی Unicode ئه و T داشته باشه یعنی ANSI/Unicode بودنش مشخص نیست و بنا به شرایط زمان کامپایل همه اون T ها در کد یا ANSI می شوند یا همه اونها Unicode می شوند.
TCHAR یعنی کاراکتری که ممکنه ANSI باشه یا Unicode باشه. یعنی برنامه نویس موقع کد نویسی تصمیم نمیگیره که کد اش برای محیط ANSI ئه یا Unicode. کامپایلر موقع کامپایل بر اساس شرایط محیط و سیستم عامل تصمیم می گیره یا تنظیم میشه که TCHAR ها یک بایتی باشند یا دو بایتی.
درباره ی ansi و unicode هم اگه کد اسکی حروف ، از 127 بیشتر نشه که مشکلی پیش نمیاد دیگه؟
نه، مشکلی پیش نمیاد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
ممنون استاد علی
جواب سئوال زیر را میدونین :
در کد زیر ، چرا دیالوگ فونت نمایش نمیده؟ :


کد:
CF_EFFECTS = 0x00000100;

hdlDll = Library.Load("Comdlg32.dll", false);
if(hdlDll) then
assignStruct = MemoryEx.DefineStruct(
{
UINT("lStructSize");
INT("hwndOwner");
INT("hDC");
UINT("lpLogFont");
INT("iPointSize");
UINT("Flags");
UINT("rgbColors");
UINT("lCustData");
UINT("lpfnHook");
UINT("lpTemplateName");
INT("hInstance");
UINT("lpszStyle");
WORD("nFontType");
INT("nSizeMin");
INT("nSizeMax");
}
);

structSize = MemoryEx.StructSize(assignStruct);
ptrStructCHOOSEFONT = MemoryEx.Allocate(structSize);
hCHOOSEFONT = MemoryEx.AssignStruct(ptrStructCHOOSEFONT, assignStruct);

hCHOOSEFONT.lStructSize = structSize;
hCHOOSEFONT.hwndOwner = mainWinHdl;
hCHOOSEFONT.Flags = CF_EFFECTS;

isOkClicked = hdlDll.ChooseFontA(ptrStructCHOOSEFONT);
    if (isOkClicked) then
  
    end
end

اما وقتی در استراکچر assignStruct ، نوع 3 تا مونده به آخر (nFontType) را از WORD به INT تغییر میدم ، کار میکنه !!
اما طبق راهنماش :
CHOOSEFONT structure (Windows)
نوع nFontType باید از نوع WORD (همون 2 بایتی بدون علامت) باشه
دلیل اش چیه؟!
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
جواب سئوال زیر را میدونین :
در کد زیر ، چرا دیالوگ فونت نمایش نمیده؟ :


کد:
CF_EFFECTS = 0x00000100;

hdlDll = Library.Load("Comdlg32.dll", false);
if(hdlDll) then
assignStruct = MemoryEx.DefineStruct(
{
UINT("lStructSize");
INT("hwndOwner");
INT("hDC");
UINT("lpLogFont");
INT("iPointSize");
UINT("Flags");
UINT("rgbColors");
UINT("lCustData");
UINT("lpfnHook");
UINT("lpTemplateName");
INT("hInstance");
UINT("lpszStyle");
WORD("nFontType");
INT("nSizeMin");
INT("nSizeMax");
}
);

structSize = MemoryEx.StructSize(assignStruct);
ptrStructCHOOSEFONT = MemoryEx.Allocate(structSize);
hCHOOSEFONT = MemoryEx.AssignStruct(ptrStructCHOOSEFONT, assignStruct);

hCHOOSEFONT.lStructSize = structSize;
hCHOOSEFONT.hwndOwner = mainWinHdl;
hCHOOSEFONT.Flags = CF_EFFECTS;

isOkClicked = hdlDll.ChooseFontA(ptrStructCHOOSEFONT);
    if (isOkClicked) then

    end
end

اما وقتی در استراکچر assignStruct ، نوع 3 تا مونده به آخر (nFontType) را از WORD به INT تغییر میدم ، کار میکنه !!
اما طبق راهنماش :
CHOOSEFONT structure (Windows)
نوع nFontType باید از نوع WORD (همون 2 بایتی بدون علامت) باشه
دلیل اش چیه؟!
دلیلش Alignment ئه. Data structure alignment
در struct هایی که کامپایلر زبان هایی مثل ++C/C میسازند که شامل API ویندوز هم میشه، ممکنه مابین فیلد های داده ای که نوع داده متفاوتی دارند، یک فاصله خالی چند بایتی ایجاد بشه تا فیلد بعدی آدرس شروعش مضربی از یک طول مشخص باشه، فرضا بعد از nFontType دو بایت خالی اضافه میشه تا nSizeMin در Offset ای قرار بگیره که مضربی از 4 بایت باشه. در بعضی ساختار های داده ای برای اینکه همچین مشکلی برای برنامه نویس ایجاد نشه، خودشون عمدا با یک فیلد بلا استفاده ای مثل reserved2 اون فضای خالی رو پوشش میدن تا با حالت Align نشده هیچ فرقی نکنه، ولی در مواردی مثل این CHOOSEFONT اینکار انجام نشده.
در #C اگه ساختار صفت StructLayoutAttribute رو ببینید یک فیلد Pack داره که مربوط به همین قضیه است. و به شیوه دیگری ببینید چطور برای اون دو بایت بلااستفاده جا در نظر گرفته :
ChooseFont
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
دلیلش Alignment ئه. Data structure alignment
در struct هایی که کامپایلر زبان هایی مثل ++C/C میسازند که شامل API ویندوز هم میشه، ممکنه مابین فیلد های داده ای که نوع داده متفاوتی دارند، یک فاصله خالی چند بایتی ایجاد بشه تا فیلد بعدی آدرس شروعش مضربی از یک طول مشخص باشه، فرضا بعد از nFontType دو بایت خالی اضافه میشه تا nSizeMin در Offset ای قرار بگیره که مضربی از 4 بایت باشه. در بعضی ساختار های داده ای برای اینکه همچین مشکلی برای برنامه نویس ایجاد نشه، خودشون عمدا با یک فیلد بلا استفاده ای مثل reserved2 اون فضای خالی رو پوشش میدن تا با حالت Align نشده هیچ فرقی نکنه، ولی در مواردی مثل این CHOOSEFONT اینکار انجام نشده.
در #C اگه ساختار صفت StructLayoutAttribute رو ببینید یک فیلد Pack داره که مربوط به همین قضیه است. و به شیوه دیگری ببینید چطور برای اون دو بایت بلااستفاده جا در نظر گرفته :
ChooseFont

ممنون استاد علی
آها
واسه همین بود که در این کدی که داده بودین :

گفتگو هایی در باب سی شارپ

اون __MISSING_ALIGNMENT__ که short بود را گذاشتین
خوب فرضا هم که ترتیب بایت ها از nFontType به هم بخوره .در کد من که در بالا دادم ، nFontType و فیلدهای بعد از اون که اصلا مقداردهی و استفاده نشدن که مهم باشه . پس چرا با اون حال ، باز هم دیالوگ فونت نمایش نمیداد؟
اما ما از کجا باید بفهمیم که چه زمانی قضیه ی alignment را باید رعایت کنیم؟ توی راهنمای این فیلد nFontType اش هم که در این باره چیزی نوشته نبود .
اصلا چرا اگه میخوان ترتیب به هم نخوره ، چرا اندازه ی nFontType را همون 4 بایت در نظر نگرفتن؟ بالاخره 2 بایت که هدر میره توسط قضیه ی alignment
درباره ی صفت StructLayoutAttribute متوجه نشدم . یعنی چی اجازه ی کنترل لایه ی فیزیکی از فیلدهای اطلاعات را میده؟!
 

the_king

مدیرکل انجمن
ممنون استاد علی
آها
واسه همین بود که در این کدی که داده بودین :

گفتگو هایی در باب سی شارپ

اون __MISSING_ALIGNMENT__ که short بود را گذاشتین
خوب فرضا هم که ترتیب بایت ها از nFontType به هم بخوره .در کد من که در بالا دادم ، nFontType و فیلدهای بعد از اون که اصلا مقداردهی و استفاده نشدن که مهم باشه . پس چرا با اون حال ، باز هم دیالوگ فونت نمایش نمیداد؟

کاری به مقادیر نداریم، شما یک حافظه با طول کمتری از چیزی که struct داخلش جا میشه در نظر گرفتید، نمیتونه از داخلش Struct رو بخونه.
اما ما از کجا باید بفهمیم که چه زمانی قضیه ی alignment را باید رعایت کنیم؟ توی راهنمای این فیلد nFontType اش هم که در این باره چیزی نوشته نبود .
تا اونجایی که به API مربوطه همیشه باید رعایت کنید، راهنما به شما کد زبان ++C/C رو نشون میده، همیشه مطابق با اصول کامپایلر های مایکروسافت عمل می کنید. اینکه تا به حال بهش توجهی نکردید به این دلیل نیست که Alignment ای در کار نبوده، به این دلیل ئه که Offset فیلد ها در جای مناسبی بوده و نیازی به جابجایی نبوده.
اصلا چرا اگه میخوان ترتیب به هم نخوره ، چرا اندازه ی nFontType را همون 4 بایت در نظر نگرفتن؟ بالاخره 2 بایت که هدر میره توسط قضیه ی alignment
اون Alignment که برای جلوگیری از کاهش سرعت دسترسی به فیلد ها است، خیلی عادیه که یک ساختار داده ای کاملا داخل یک Page حافظه نباشه و بین Page ها تقسیم بشه. تصور کنید فیلدی نصفش در انتهای یک Page حافظه باشه و نصفش در ابتدای Page بعدی. دسترسی به این فیلد میتونه خیلی برای سیستم عامل و پردازنده سربار داشته باشه. اگر هم بیان کلا جلوی این مشکل رو بگیرند و طول همه فیلد ها رو فرضا مضربی از 4 یا 8 قرار بدن که فیلد ها تا حد امکان بصورت کامل در یک Page باشند، قطعا فضای زیادی رو در برنامه ها هدر دادن. با این قواعد Alignment در عین حال که نمیخوان خیلی حافظه اضافه ای هدر بدن، سعی می کنند بین دو پارامتر فضای حافظه و کارایی یک توازن رو برقرار کنند.
با نظرتون موافقم که میشد متغیر 4 بایتی رو انتخاب کرد ولی سلیقه طراح ئه، قانون و قاعده خاصی نداره، چه nFontType دو بایتی باشه و چه چهار بایتی، اون دو بایت بیشتر استفاده ای برای سازنده اش نداشته. در ضمن برنامه نویسانی که با API کار میکنند هم به این قواعد کامپایلر آشنا هستند و هم به موقعیت تک تک فیلد ها که اهمیتی نمیدن، هر جا که باشه با اسمش کار دارند، نه Offset اش. اصول و قواعدش هم که مطابق کامپایلر های مایکروسافته.
درباره ی صفت StructLayoutAttribute متوجه نشدم . یعنی چی اجازه ی کنترل لایه ی فیزیکی از فیلدهای اطلاعات را میده؟!
تقریبا. در کامپایلر زبان های مختلف شیوه های مختلفی برای تعیین محل قرار گیری فیلد ها هست که ممکنه با پیشفرض یک زبان دیگه تفاوت داشته باشه، این صفت کمک می کنه که بشه سازگاری بین ساختار struct داخل #C و مورد خارجی رو حفظ کرد. چطور که وقتی در #C یک فیلد داخل struct از نوع string ئه، در نمونه خارجی ممکنه Unicode باشه یا نباشه، که این StructLayoutAttribute میتونه اینجا با فیلد CharSet فرضا حالت CharSet.Ansi رو تعیین کنه.
 

جدیدترین ارسال ها

بالا