دوست من ، شما ظاهرا سوال ایشون رو درست متوجه نشدین و به بحث های مطرح شده توی تاپیک دقت نکردید !
پروژه ای که شما ارئه کردید بازهم فرم داره ، ایشون پروژه داشتند که فرمی نداشت و میخواستند که توی اون از تایمر استفاده کنند . اگر توضیحات رو دنبال کنید بهتر متوجه میشید
اگه دقت کنید توی فرم هیچ نوع تایمری به کار نرفته !
بازهم متوجه نشدید
شما فکر کن که یک پروژه ای داری که فقط توش یک Module (موژول ) هست و نه هیچ چیزه دیگه . در واقع اصلا فرمی نباید در کار باشه !!! مثلا یک برنامه کنسول که از sub main شروع میشه و هیچ فرمی هم نداره !
سلام.
بذار این جوری بگم. برای این که اون تایمر کار کنه باید فرم هم موجود باشه. چون همون طور که darg گفت پیغام رو به فرم میفرسته.
من حتی کد های فرم رو داخل ماژول کپی کردم ولی ارور داد.
سلام.
بچه ها این تایمر رو ببینید. بدون فرم کار میکنه. ولی روشش استاندارد نیست. تو برنامه حلقه بی پایان وجود داره. ولی کدهای تایمر داخل حلقه نیست و داخل تابع خود تایمره.
اگه میشد از روشی غیر از حلقه بی پایان برای جلوگیری از بسته شدن ماژول استفاده کرد میشد اسمشو گذاشت تایمر.
استفاده از حلقه برای ایجاد حتی تاخیر توی برنامه هم مناسب نیست . مشکل حلقه اینجاست که کلی از Cycle های CPU رو بیخودی مصرف میکنه به این صورت که سیستم عامل وظیفه داره به برنامه شما مقداری زمانی رو برای اجرا اختصاص بده ، در نتیجه خیلی از اون مقدار زمان و قدرت CPU توی برنامه شما بعلت وجود حلقه تلف میشه .
خود سیستم عامل مثلا تابعی رو ارائه میکنه مثل sleep که برای شما اینکار رو انجام میده و کلا از دادن زمان و قدرت CPU به برنامه شما توی اون مدت خودداری میکنه پس از هدر رفتن زمان و قدرت CPU جلوگیری میکنه ! این حالت رو فقط سیستم برنامه دهی یا scheduling ویندوز میتونه مدریت کنه .
تایمر هم مشابه هست . تایمر ها توی سیستم از وقفه سخت افزاری استفاده میکنند و سیستم عامل اونها رو مدیریت میکنه . پس استفاده از حلقه برای ساخت تایمر کار جالبی نیست !
سلام.
ممد اصلا تایمر من رو دیدی؟ من تو حلقه تابع sleep رو گذاشته بودم تا به cpu فشار نیاد. البته خودمم گفتم روش کار استاندارد نیست. چون اون کدی که داخل تابع تایمر قرار داره رو میشه داخل خود حلقه هم گذاشت. در کل روش جالبی نیست. ولی من بیشتر به این دلیل گفتم ببین چون شما و darg گفتید پیغام تایمر باید به فرم ارسال شه ولی در این پروژه اصلا فرم وجود نداره. دانلود کن ببین.
خوب من یک اشتباهی کردم... که فکر می کردم حتما باید هندل با ارزش داد برای ایجاد
تایمر!
که در برنامه شما با هندل صفر تونسته تایمر رو بسازه نمی دونستم...
ولی مشکل اینجاست که سیستم در زمانی که می خواد مثلا فرم رو ببینده با توجه به
هندلش تایمر های وابسته رو هم خواهد بست. اما در کد شما هندلی وجود نداره بنابراین
حتی وقتی که برنامهتون رو در ویژوال بیسیک Stop می کنید باز هم تایمر به کار خودش
ادامه می ده!
اما منظور کلی من و بخصوص محمد2003 این بود که در ماژول تنها ما پایان عمر برناممون
همون پایان کد های ساب ماین هست! که در فرم این اتفاق نمی افته, پس ایجاد تایمر
در ماژول بی معنی میشه که البته شما با اون حلقه تونستید این مشکل رو هم حل کنید!
یک سوال دیگه: شما با ارسال Sleep 500 چطور می خوایند تطابق ایجاد کنید با عدد
تناوب تایمر که ازش کوچیکتره؟
برنامه رو دیدم و به نتیجه جالبی رسیدم که خیلی از فرضیات من رو نقض میکنه ! شاید بهتر بود اینطور بیان میکردم که وجود پنجره یا Window الزامیه نه فرم چون متوجه شدم فرم توی ویژوال بیسیک الزاما پنجره نیست !
به این خط از برنامه خودت دقت کن :
کد:
lngTimerID = SetTimer(0, 0, 200, AddressOf TimerProc)
در مورد کد شما ، مایکروسافت میگه اگر شما توی تابع settime مقدار صفر رو به عنوان پارامتر اول یا هدل پنجره ارسال کنی ( توی خط بالا پارامتر اول صفر هست ) و از تابع callback استفاده کنی ( همون تابع با نام TimerProc) خودت مسئولی که پیغام های WM_TIMER رو dispatch کنی . یعنی چی ؟ یعنی اینکه چون شما هندل هیچ پنجره ای رو مشخص نکردی این وظیفه خودته که پیغام های WM_TIMER رو به پنجره منورد نظرت بفرستی .این مرحله توی یک برنامه C تحت ویندوز اینطور نوشته میشه :
کد:
HWND hwndTimer;
MSG msg;
while (GetMessage(&msg,
NULL,
0,
0))
{
// Post WM_TIMER messages to the hwndTimer procedure.
if (msg.message == WM_TIMER)
{
msg.hwnd = hwndTimer;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
اما متاسفانه ویژوال بیسیک خودش این عملیات رو برای ساده تر کردن کار شما پشت پرده انجام میده . حدسی که من میزنم و علت اینکه تایمری که شما نوشتی درست عمل میکنه یک چیز بیشتر نیست . اونهم اینکه توی وی بی همه برنامه ها پنجره دارند ( چه کنسول و چه فرم دار و ... ) فقط ویژوال بیسیک کلاس اون پنجره اصلی رو اتوماتیک رجیستر میکنه ولی نمایشش نمیده !!! چیزی که متوجه شدم این بود که بر خلاف برنامه های C تحت ویندوز ، برنامه های ویژوال بیسیک توی این زمینه فرق دارند و سیستم اتوماتیک بررسی پیغامش کلا آدم رو میتونه تا ناکجا آباد ببره !!
نقل قول: ولی مشکل اینجاست که سیستم در زمانی که می خواد مثلا فرم رو ببینده با توجه به
هندلش تایمر های وابسته رو هم خواهد بست. اما در کد شما هندلی وجود نداره بنابراین
حتی وقتی که برنامهتون رو در ویژوال بیسیک Stop می کنید باز هم تایمر به کار خودش
ادامه می ده!
این مشکل از اونجا آب میخوره که برنامه های ویژوال بیسیک توی محیط ویژوال بیسک کامپایل نمیشن بلکه شبیه سازی یا تفسیر میشن ( interpret ) اگر شما برنامه رو کامپایل کنی مشکل حل میشه !
نکته ای که پیمان جان نباید فراموش بکنی اینه که همون طور که گفتم اینکه شما توی برنامه ویژوال بیسیک حضور WM_TIMER رو احساس نمیکنی وجود سیستم اتوماتیک کنترل و dispatch پیغامی هست که بطور اتوماتیک و پشت پرده داره به شما حال میده !!
نه اینکه وجود نداره . اگر با ساختار برنامه های ویندوز آشنا باشید حتما میدونید که برنامه های ویندوز یک حلقه بررسی پیغام دارند در صورتیکه توی وی بی همچین چیزی مفهوم نداره . خود وی بی وظیفه کنترل پیغام ها رو بر عهده میگیره و گاهی هم اینطور سردرگمی ها رو هم ایجاد میکنه !