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

شروع موضوع توسط SajjadKhati ‏12 نوامبر 2017 در انجمن منطق و الگوریتم برنامه‌نویسی

  1. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    1,049
    تشکر شده:
    364
    امتیاز دستاورد:
    83
    سلام
    استاد علی ، در قضیه ی استفاده از تابع api برای فونت ، در استراکچر CHOOSEFONT ، فیلدی بنام lpTemplateName و lpszStyle دارن که به ترتیب از نوع های LPCTSTR و LPTSTR هستن که کلا رشته هستن ولی برخلاف فیلد lfFaceName در استراکچر CHOOSEFONT که از نوع TCHAR و کلا رشته هست و در فیلد lfFaceName ، گفت که 32 بایت لازم داره ؛ ولی در فیلدهای lpTemplateName و lpszStyle نگفت . در اینجا باید چند بایت براشون فضا بگیریم؟ و از کجا باید متوجه بشیم چند بایت بگیریم؟ آخه گفتین که 1 بایت کم و زیاد شدن برای استراکچر ، خطا میده
    دوم اینکه هر جا نوع کاراکتر ، ansi بخواد (8 بیت) ولی ما نوع کاراکتر رو ascii بدیم (7 بیت) ، برای نام فونت (و هر چیزی که اسم میخواد) ، اشکال داره؟
     
    نوشته شده توسط SajjadKhati در ‏12 نوامبر 2017
  2. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    1,049
    تشکر شده:
    364
    امتیاز دستاورد:
    83
    من که قاتی کردم
    کد زیر رو نوشتم ولی تا حالا که دیالوگ فونت بالا میومد ، همین قدر هم دیگه بالا نمیاد! :


    کد (Text):
     _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
     

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


    کد (Text):
    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 در ‏13 نوامبر 2017
  3. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    1,049
    تشکر شده:
    364
    امتیاز دستاورد:
    83
    سلام مجدد
    کدش رو فهمیدم یعنی مقدار بازگشتی نام رشته رو درست برمیگردونه


    کد (Text):
    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 کاراکتر جلوتر مینویسم یعنی قسمتی از کد بالا رو به شکل زیر تغییر میدم :


    کد (Text):
         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 رو انتخاب نمیکنه .
    چرا؟!! نمیدونم
     
    نوشته شده توسط SajjadKhati در ‏13 نوامبر 2017
  4. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,589
    تشکر شده:
    10,590
    امتیاز دستاورد:
    113
    شما ساختار 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 ای که باشه مشکل سازه.
    با مسیر فایل و فولدر مشکل دارند، با اسامی فونت مشکل دارند، با اسامی فیلد های پایگاه داده و مرتب سازی رشته ها و کاراکتر های کنترلی متن و پاراگراف بندی و ...
     
    نوشته شده توسط the_king در ‏13 نوامبر 2017
    SajjadKhati از این پست تشکر کرده است.
  5. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    1,049
    تشکر شده:
    364
    امتیاز دستاورد:
    83

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

    درباره ی ansi و unicode هم اگه کد اسکی حروف ، از 127 بیشتر نشه که مشکلی پیش نمیاد دیگه؟
     
    نوشته شده توسط SajjadKhati در ‏13 نوامبر 2017
  6. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,589
    تشکر شده:
    10,590
    امتیاز دستاورد:
    113

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

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

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


    کد (Text):
    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 بایتی بدون علامت) باشه
    دلیل اش چیه؟!
     
    آخرین ویرایش: ‏25 می 2018
    نوشته شده توسط SajjadKhati در ‏25 می 2018
  8. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,589
    تشکر شده:
    10,590
    امتیاز دستاورد:
    113
    دلیلش Alignment ئه. Data structure alignment
    در struct هایی که کامپایلر زبان هایی مثل ++C/C میسازند که شامل API ویندوز هم میشه، ممکنه مابین فیلد های داده ای که نوع داده متفاوتی دارند، یک فاصله خالی چند بایتی ایجاد بشه تا فیلد بعدی آدرس شروعش مضربی از یک طول مشخص باشه، فرضا بعد از nFontType دو بایت خالی اضافه میشه تا nSizeMin در Offset ای قرار بگیره که مضربی از 4 بایت باشه. در بعضی ساختار های داده ای برای اینکه همچین مشکلی برای برنامه نویس ایجاد نشه، خودشون عمدا با یک فیلد بلا استفاده ای مثل reserved2 اون فضای خالی رو پوشش میدن تا با حالت Align نشده هیچ فرقی نکنه، ولی در مواردی مثل این CHOOSEFONT اینکار انجام نشده.
    در #C اگه ساختار صفت StructLayoutAttribute رو ببینید یک فیلد Pack داره که مربوط به همین قضیه است. و به شیوه دیگری ببینید چطور برای اون دو بایت بلااستفاده جا در نظر گرفته :
    ChooseFont
     
    نوشته شده توسط the_king در ‏25 می 2018
    SajjadKhati از این پست تشکر کرده است.
  9. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    1,049
    تشکر شده:
    364
    امتیاز دستاورد:
    83

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

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

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

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,589
    تشکر شده:
    10,590
    امتیاز دستاورد:
    113

    کاری به مقادیر نداریم، شما یک حافظه با طول کمتری از چیزی که struct داخلش جا میشه در نظر گرفتید، نمیتونه از داخلش Struct رو بخونه.

    تا اونجایی که به API مربوطه همیشه باید رعایت کنید، راهنما به شما کد زبان ++C/C رو نشون میده، همیشه مطابق با اصول کامپایلر های مایکروسافت عمل می کنید. اینکه تا به حال بهش توجهی نکردید به این دلیل نیست که Alignment ای در کار نبوده، به این دلیل ئه که Offset فیلد ها در جای مناسبی بوده و نیازی به جابجایی نبوده.

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

به اشتراک بگذارید