مقدمه :
واژه API مخفف شده سه كلمه Application Programming Interface ميباشد آن يك رابط نرم افزار است كه در برنامه هاي ديگر استفاده ميگردد. همانند صفحه كليد ماشين حساب كه رابط ميان كليد و عدد نمايش داده شده ميباشد.يك API رابط نرم افزاري سيستم هاي عامل ميباشد API يك سيستم عامل دليلي بنيادي و اساسي ميباشد براي عدم هماهنگي سيستمهاي عامل با هم .
براي مثال يك قطعه در يك سيستمي بر پايه مكينتاش نميتواند در ويندوز اجرا شود (البته بدون وجود شبيه ساز آن) زيرا سيستم عامل مكينتاش و ويندوز API هاي متفاوتي دارند.
تابع Core در يك شبيه ساز تبديل ميشود ( API صدا شده در يك برنامه فرا ميخواند آن را از سيستم عامل) در حقيقت يك ترتيب انتقال ميان دوAPI وجود دارد.
يك API واقعا يك برنامه با سطح پايه براي برنامه هاي سطح بالا ميباشددر يك برنامه سطح بالا(high-level) ، يك برنامه بجاي اينكه بارها قسمتي از برنامه خود را اجرا كند از برنامه هاي ديگر كمك ميگيرد.براي مثال يك برنامه ميخواهد يك سري داده را برروي ديك بنويسد ، اين كار را دستي انجام نميدهد بلكه دستورات را ارسال ميكند خود هارديسك جستجو ميكند ، ميخواند و مينويسد بيت به بيت .
در عوض انحصارا اين سيستم عامل هست كه اطلاعات را داخل يك فايل مينويسدو در واقع سيستم عامل است كه كارهاي سخت را هندل ميكندو انجام ميدهد. اين كار بسيار سودمند است زيرا، طراح نرم افزار هرگز نگراني در رابطه با برنامه هاي پايه اي نداردو خود را ديگير مسايل بنيادي نميكند، در يك برنامه مسايل بنيادي و اساسي مانند دسترسي به ديسك و تخصيص حافظه و كشيدن روي مانيتور و... ميباشد.
اگر هر برنامه شخصي مستقيما ميخواست همه خروجي هاي (مثلا گرافيكي) را خود هندل كند در نتيجه نياز بود به اينكه با تغيير سيستم برنامه نيز به روز رساني شود و توسعه داده شود . در عوض اگر همه آنها از API استفاده كنند با تغيير سيستم و به روز رساني سيستم عامل همه آنها هم ميتوانند به كار خود ادامه دهند حتي بدون يك تغيير كوچك.
وظایف توابع API :
اساسا API ويندوز هندل ميكند همه چيزهارا در ويندوز. بطور معمول API شامل همه چيزها همانند كشيدن بروي مانيتور،دسترسي به ديسك ، رابط چاپگر ، استفاده از اينترنت و ... ، توجه كنيد كه همه برنامه هاي پايه اي ويندوز نيز از API استفاده ميكند . براي مثال ديالوگ باكسها(Openو Save و انتخاب فونت و ...) و شل ويندوز و ليست باكسها و انتخابهاي (Setting) سيستم عامل و هر چيز ديگر ويندوز توسط API آماده ميشود. برنامه ها با پايه ويندوز بطور وسيعي از API استفاده ميكنند تقريبا براي هر عملي كه ميخواهند انجام دهند. حتي اگر شما در برنامهايتان به صورت واضح از توابع API استفاده نكنيد زبان برنامه نويسي شما(مثلاVB) براي هر عمل در برنامه شما تقريبا توابع API را صدا ميكند . در واقع ميتوان گفت API ويندوز بصورت كامل و وسيع احاطه دارد به همه موضوعات .
محل قرار گیری :
تقريبا هر تابع از API ويندوز را در يك DLL(Dynamic Link Library) فايل واقع در C:\Windows\System (يا در واقع در دايركتوري سيستم ويندوز نصب شده) ميتوان پيدا كرد. اين DLL فايلها توابع داخلشان را به خارج ميفرستند و اجازه ميدهند به برنامه هاي خارجي ديگر كه از اين توابع استفاده كنند. اين نوع طراحي به هر برنامه بر پايه ويندوز اجازه ميدهد با يك ارتباط ساده به توابع API دسترسي داشته باشند. تعداد زيادي از توابع API را ميتوان در فايهاي USER32(User Interface Functions) و Kernal32.dll ( Operating system Kernal Functions) و gdi32.dll(Graphics Device Interface Functions) و shell32.dll(Windows shell functions) پيدا كرد.
اجزای یک تابع :
اگرچه ما فقط در اين قسمت از توابع ويندوز گفتيم اما اين توابع خود جزي از API ويندوز ميباشند در زير ليستي از مشخصات اجزاي داخلي سازنده آ پي اي را نشان ميدهيم
Functions : دوباره اشاره ميكنيم كه توابع سازنده اصلي ا پي اي ويندوز ميباشند و آنها هر كدام كدهايي هستد كه اعمال ا پي اي را انجام ميدهند.و انها در فايهاي DLL ذخيره شده اند و به آساني توسط برنامه هاي بر پايه ويندوز قابل استفاده ميباشند.
Structures : تركيبي از متغيرهاي مختلف ميباشد، به صورت متناوب استفاده ميشونداكثر توابع ا پي آي نيازمند استراكچرها ميباشند زيرا با استفاده از يك استركچر ميتوان اطلاعات بسياري را به يك تابع پاس داد بدون اينكه از تعداد زيادي پارامتر براي اين كار استفاده نمود. اگر چه استركچرها در داخل ا پي آي ها تعريف شده اند اما شما بايد در برنامه خودتان نيز آنها را تعريف كنيد.
Named Constants : ا پي آي ويندوز بصورت متناوب از كد هاي عددي استفاده ميكند كه به آنها ثابتها گفته ميشود . نام اين ثابتها تعريف شده است و يك راه بسيار ساده براي ارجاع به مقدار ارزش هر ثابت ميباشد. گاهي مواقع از اين ثابتها به عنوان پرچم (Flage) استفاده ميشودمقدارداده ميتواند بصورت دو دويي با پرچم هاي ديگر تركيب شود. همانند استركچرها بايد ثابها نيز در برنامه خودتان تعريف شوند.
Callback Functions : اين تابعي است كه توسط توابع API فراخواني ميگردد ولي تابع خود توسط برنامه نويس ساخته ميشود .براي توضيح بيشتر به مطلب زير توجه نماييد : يك سري توابع و روتين ها هستند كه بايد توسط برنامه نويس ايجاد گردند ولي اين روتينها را برنامه نويس نميتواند از طريق برنامه فراخواني كند مانند تابع كليك روي يك شي ( در واقع Click Event يا روتين OnClick) كه وقتي روي يك شي كليك زده ميشود اين تابع بايد فعال شود كه توسط برنامه نويس تهيه گرديده است ولي فراخواني آن و اجراي آن به عهده توابع API ميباشد و خود برنامه نويس نميتواند آن را فراخواني نمايد.
Messages : نوعي خاص از نام ثابتها ميباشند.در ثابتها مقادير عددي به يك نام نسبت داده شده است اما Messages ارسال ميكند يك شي را (به پنجره اي خاص)
چرا نگران ؟
امتياز! استفاده از توابع API ويندوز در اين است كه آنها پر از اشكال هستند. اول اينكه همه توابع API همانند ديگر زبانهاي برنامه نويسي نسبت به خطا حساس هستند زيرا همه توابع را با زبان برنامه نويسي C++ نوشته اند و همه مقادير پاس داده شده و برگشت شده از تابع بايد با اصول زبان برنامه نويسي C++ همخواني داشته باشد صرفنظر از اينكه با چه زباني برنامه نويسي ميكنيد . اين خود ميتواند يك مشكل باشد وانگهي توابع API در برابر خطا عكس عمل هاي غيرعادي از خودشان نشان ميدهند مثلا بجاي اينكه با يك ديالوگ باكس و يك اخطار خطا را نشان دهد باعث قفل شدن سيستم و يا خاموش شدن آن ميشود(حتي با يك خطا كوچك) لذا از اين روست كه در زبان برنامه نويسي ويژوال بيسيك هيچ نوشته اي راجع به توابه API نميتوان يافت و براي پيدا كردن آنها نياز به جستجو در سايت ها ميباشيم.بنابراين نبايد آنقدرها هم نگران بود!!
به زباني ساده : توابع API بسيار قدرتمندتراز خثوثيات زيباي زبانهاي برنامه نويسي ديگر ميباشد بخصوص ويژوال بيسيك مثلا در ويژوال بيسيك شما ميتوانيد تيتر يك پنجره ساخته شده توسط برنامه را با تغيير دادن مقدار خصوصيت Caption عوض كنيد ولي اگر اين پنجره توسط برنامه ديگري ساخته شده بود چه ؟ براي مثالي ديگر فرض كنيد ميخواهيم از پنجره Open فايل استفاده نماييم (با فرض عدم استفاده از توابع API ) لذا بايد از يك فايل كتابخانه اي OCX با حداقل حجم 90Kb استفاده كنيم.(يعني90Kb به حجم برنامه شما اضافه ميگردد) . اما با استفاده از تابع GetOpenFileName شما به همان پنجره دسترسي داريد بدون نياز به فايل OCX و اگر شما بخواهيد در رجيستري ويندوز بنويسيد يا بخوانيد و يا از جويستيك استفاده نماييد ، ويژوال بيسيك ابزارهاي لازم را در اختيارتان قرار نميدهد و نياز به API ويندوز داريد هرجند كه با اشكال مواجه شويد پس زياد هم نگران استفاده از API ويندوز نباشيد.
بطور اختصار ، اگر از ويژوال بيسيك يا هر زبان برنامه نويسي ديگري كه استفاده ميكنيد قابليت انجام يك كار را داشته باشد بهتر است از API ويندوز استفاده نكنيد چون براي شما استفاده آسانتر و مطمئنتر مهم است ، اما اگر ميخواهيد به برنامه تان قابليت هاي قوي اضافه كنيد نميتوانيد از ويژوال بيسيك استفاده كنيد و لازم است به سمت API ويندوز برويد. در اين راهنما سعي شده براي كاربراني كه آشنا به ويژوال بيسيك هستند با استفاده از مثال هايي روشهاي لازم جهت استفاده از صدها تابع API دربرنامه نويسي آموزش داده شود.
شروع کار :
در ظاهر استفاده از توابع API ساده و آسان بنظر ميايد قبلا شما براي استفاده از يك تابع نخست بايد آن را يك جايي در برنامه تان تعريف ميكرديد سپس از آن استفاده ميكرديد. شما در اينجا خواهيد ديد چگونه ميتوان يك تابع API را تعريف كرده(در ويژوال بيسيك) و از آن استفاده نمود.
نحوه تعریف توابع :
قبل از اينكه بتوانيد يك تابع API را در ويژوال بيسيك استفاده نماييد بايد آن را نخست تعريف ومشخص نماييد. براي تعريف تابع بايد به ويژوال بيسيك بگوييد كه چگونه ميتواند آن را پيدا نمايد. براي تعريف نخست نام تابع سپس نام فايل DLL حامل تابع و سپس پارامترهاي موردنياز آن به همراه نوع آنها و نوع مقدار برگشتي(در صورت موجود بودن). با اين اطلاعات ويژوال بيسيك ميداند كه تابع API را از كجا پيدا نمايد البته اين رويه منحصر به توابع API نيست و هر تابعي كه درون يك DLL فايل قراردارد نيز بايد همانند روش بالا تعريف گردد.
در زير روش تعريف تابع نشان داده شده است. دستور Declare براي تعريف تابع استفاده ميشود ، اين دستور ميتواند داخل يك ماجول يا يك فرم بكار گرفته شود اگر داخل فرم استفاده شود بايد پيشوند Private براي آن بكار گرفته شود و اگر داخل يك ماجول بكار رود ميتواند با يكي از دو پيشوند Public و يا Private مورد استفاده قرار گيرد ، توجه نماييد استفاده از واژه Public باعث ميگردد تابع در بقيه قسمتهاي برنامه نيز قابل استفاده باشد ولي واژه Private باعث ميگردد تابع فقط در همان ماجولي كه تعريف شده قابل استفاده باشد.
کد:
[{Public | Private}] Declare Function function_name Lib "DLL_filename" [Alias "function_alias"] (argument_list) As data_type
روش تعريف تابع در بالا نشان داده شده است حال به تعريف هر يك از اجزاي (به صورت ايتاليك نوشته شده اند) توجه نماييد ..
function_name :
نام تابع API ميباشد. اين نامي است كه ويژوال بيسيك با آن به تابع رجوع ميكند . از نظر تئوري اين نام هرجيزي ميتواند باشد(به قسمت Alias توجه نماييد) اما بهترين حالت اين است كه آن نام ، نام رسمي و تعيين شده API ويندوز باشد.
DLL_filename :
نام DLL فايلي كه اين تابع در داخل آن قرار دارد آن نام نميتواند شامل مسير هم باشد(Path) زيرا همه DLL فايلها داخل دايركتوري سيستم ويندوز قراردارند(\Windows\system)و همچنين اين نام نبايد پسوند .dll داشته باشد يعني براي برنامه دونام فايل user32 و user32.dll يكسان هستند. البته تعدادي از توابع API وجود دارند كه از اين قاعده پيروي نميكنندمثلا تعدادي از ئوابع API مربوط به چاپگر در داخل فايل Winspool.drv قراردارند. در اين حالت بكارگيري پسوند الزلمي است.
function_alias :
(اختياري) اين نامي است كه در داخل فايل DLL قراردارد. توجه نماييد اين نام بسيار مهم ميباشد بخصوص براي آنهايي كه داراي پارامتر از نوع استرينگ ميباشند زيرا ما دو گونه تابع API داريم يكي گونهANSI كه بيشتر براي زبانهاي محاوره استفاده ميشود و ديگري گونه Unicode است كه براي زبانهايي با پهناي كاراكتري زياد (مانند زبان چيني كه تعداد كاراكترهاي آن از 256 بيشتر است)
argument_list :
يك ليست خالي يا با تعدادي از متغيرها و پارامترهايي كه تابع به آنها نياز دارد ، اين ليست بسيار شبيه ليست تعريف متغيرها در توابع ويژوال بيسيك ميباشد البته نحوه كار كمي متفاوت است كه در قسمتهاي بعد توضيح داده ميشود.
data_type :
نوع داده اي كه تابع برميگرداند ، بايد دانست بيشتر تابع ها داده اي از نوع Long برميگردانند ولي تعدادي از توابع نيز مقدار String را بر ميگردانند.
بعضي از توابع مقداري برنميگردانند تعريف اين گونه توابع كمي با روش تعريف ذكر شده در بالا متفاوت ميباشد. كه در زير نمونه آن را مشاهده میکنید .
کد:
[{Public | Private}] Declare Sub function_name Lib "DLL_filename" [Alias "function_alias"] (argument_list)
ليست پارامترها :
ليست متغيرها و آرگومانها نشان ميدهد كه چه تعداد متغير و از چه نوعي بايد به تابع پاس داده شود.از نظر نحوه تعريف خيلي مشابه تعريف تابع يا ساب(Sub) در ويژول بيسيك ميباشد.در زير نحوه تعريف آرگومانها شرح داده شده است..بعضي از توابع هيچ متغيري دريافت نميكنند بنابر اين نبايد هيچ متغيري به آنها پاس داد.
کد:
[{ByVal | ByRef}] argument_name As data_type, ...
بجز انتخاب هاي ByVal و ByRef احتمالا شما با نوع دادها آشنا بوده و نحوه تعريف را بدانيد ولي براي اطمينان در زير شرح نحوه تعريف توضيح داده شده است.
argument_name :
نام آرگومان و پارامتر مورد نياز ، توجه كنيد اين نام بواقع فقط مشخص كننده پارامتر ميباشد و انتخاب نام پارامتر اختياري بوده و شما ميتوانيد براي آن نام ديگري انتخاب كنيد .
data_type :
نوع پارامتر را مشخص ميكند و آن توسط چند كليد واژه مشخص ميگردد كه هركدام مشخص كننده يك نوع داده ميباشند.
انواع دادها :
شما اين را قبلا ميدانستيد كه هر داده يك اندازه و يك فرمت مخصوص به خود را دارد توابع API تعداد خاصي از دادها را پشتيباني ميكنند كه اين نوع دادها همه در ويژوال بيسيك نيز موجود است در زير ليستي از دادهايي كه توسط توابع API پشتيباني ميگردد آمده است.
Byte :
يك عدد صحيح با طول 8 بيت.
Integer :
يك عدد صحيح با طول 16 بيت
Long :
يك عدد صحيح با طول 32 بيت
String :
يك استرينگ با طول مختلف
در مجموع انواع دادههاي ذكر شده و هر استراكچرAPI (Structure) را ميتوان بكار برد.در مورد استراكچرها قبلا مقدمه اي توضيح داده شده است. از چهار نوع داده اشاره شده دو نوع Long و String بيشترين كاربرد را دارند زيرا ويندوز يك سيستم عامل 32بييتي ميباشد (آغاز اين نوع سيستم عامل به ويندوز 95 و ويندوز ان تي 3.1 برميگردد) تقريبا همه اعداد بكار رفته در API از نوع عدد صحيح (32bits)Long هستند . استرينگ هم بصورت متناوب مورد استفاده قرار ميگيرد زيرا تنها روش ذخيره و نگهداري كلمات ميباشد.
ByVal و ByRef :
دو كليد واژه ByVal و ByRef روشهاي خاص ارسال متغيرها و پارامترها به توابع API هستند . اين دو روش كاملا از هم متمايز هستند و با هم هيچ وجه اشتراك ندارند.و شما نميتوانيد يكي را جايگزين ديگري بكنيد.روش و متد ByRef به طور معمول استفاده ميشود مگر اينكه به صراحت از ByVal استفاده شود به همين دليل شما در موقع تعريف توابع API كلمه ByRef را نميبينيد و فقط به كلمه ByVal نياز ميباشد.
اينجا گوشزد ميشود كه به معناي واقعي اينها بايد توجه نمود ، اگر چه دانستن تفسير واقعي اين دو بسيار مشكل است(براي استفاده ماهرانه از توابع API دانستن اين تفسير بسيار ضروري ميباشد) اما در زير به صورت عمده در مورد هر يك شرح مختصر داده ميشود.
ByVal : دقيقا به معني با مقدار ميباشد(By Value) مقدار يك متغير كه پاس داده ميشود به عنوان يك پارامتر. اين متد باعث ميشود كه تابع API نتواند محتويات متغير را تغيير دهد به عنوان مثال اگر يك متغير با نام MyVal داشته باشيم كه بوسيله متد ByVal به يك تابع API پاس داده شده باشد تابع نميتوان مقدار آن را اديت كرده يا تغيير دهد.
ByRef : دقيقا به معني با مرجع (By Reference) ميباشد . يعني به جاي پاس دادن محتويات يك متغير به تابع يك مرجع ( مقداري كه با آن به مقدار يك متغير ميتوان دسترسي داشت) به آن پاس داده ميشود.اين متد اجازه دسترسي و اديت و اصلاح مقدار يك متغير را ميدهد. توجه كنيد كه نميتوان يك مقدار ثابت را به وسيله اين متد پاس داد. معمولا اين متد در موقعيث استفاده ميشود كه بخواهيم به جاي برگرداندن يك مقدار از تابع يك سري اطلاعات را برگشت بدهيم.
يك سري نكات اضافي وجود دارد كه بايد در مورد اين دو متد بخاطر سپرد.
1- استرينگها اغلب پاس داده ميشود با متد ByVal هرچند كه تابع API اين قابليت را دارد كه به محتويات آن دسترسي داشته و آن را اديت نمايد.
2- كليه استراكچرهاي تعريف شده توسط كاربر ( شامل استراكچرهاي استفاده شده توسط خود توابع API نيز ميگردد) بايد با متد ByRef پاس داده شوند
3- آرايه ها اغلب با ByRef پاس داده ميشوند
4- مقادير عددي با هر دو متد پاس داده ميشوند فقط بايد ديد كداميك مورد نياز ميباشد.
مثال :
در اين صفحه ها شما نجوه تعريف و استفاده از دستور Declare را ديديد ، در وحله نخست اين دستور بسيار سخت به نظر ميايد اما شما نياز به اين تعريف نداريد و ميتوانيد با استفاده از API Viewer ويژوال بيسيك به اين تعاريف دسترسي داشته باشيد و يا ميتوانيد با استفاده از اين كتاب عمل تعريف كردن را انجام دهيد.
در زير ليستي از نحوه استفاده از دستور Declare را مشاهد ميكنيد.
در زير نحوه تعريف تابعي را كه هيچ مقداري دريافت نميكند و يك مقدار عددي 32بيتي برميگرداند را مشاهده ميكنيد:
کد:
Declare Function GetDesktopWindow Lib "user32.dll" () As Long
تابعي كه يك مقدار عددي 32بيتي را دريافت ميكند و هيچ مقداري برنميگرداند.
کد:
Declare Function Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
تابعي كه يك عدد 32بيتي دريافت ميكند و يك عدد 32بيتي نيز برميگرداند.
کد:
Declare Function ReleaseDC Lib "user32.dll" (ByVal hWnd As Long, ByVal hDC As Long) As Long
در زير يك تابع كه يك استرينك را دريافت ميكند و استرينگ ديگري را برميگرداند(توجه كنيد همانند بقيه توايع API كه با استرينگ ها كار ميكنند بايد حتما از دستور آلياس استفاده كرد).
کد:
Declare Function CharUpper Lib "user32.dll" Alias "CharUpperA" (ByVal lpsz As String) As String
تابع فوق يك مقدار از نوع استراكچر با نام RECT دريافت ميكند و يك مقدار 32بيتي برميگرداند.
کد:
Declare Function CreateRectRgnIndirect Lib "gdi32.dll" (lpRect As RECT) As Long
اين تابع سه مقدار دريافت ميكند دو مقدار نخست عددي از نوع 32بيتي و مقدار سوم نيز 32بيتي است ولي توسط تابع تغيير ميكند(ByRef) و مقدار دهي ميشود و خود تابع نيز مقداري عددي 32بيتي برميگرداند.
کد:
Declare Function SHGetSpecialFolderLocation Lib "shell32.dll" (ByVal hwndOwner As Long, ByVal nFolder As Long, ppidl As Long) As Long
در پايان هم تابعي كه شامل هر نوع داده به عنوان پارامتر در ورودي بوده و يك عدد 32بيتي در خروجي دارد.
کد:
Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, phkResult As Long, lpdwDisposition As Long) As Long
بايد توجه كنيد براي كار با توابع API دانستن اطلاعات ذكر شده در بالا بسيار ضروري ميباشد و در صورت نياز شما بايد اين مطلب را چند بار مرور كنيد تا بتوانيد از آن در برنامهايتان استفاده نماييد.
موفق و پیروز باشید .