ورود

نسخه کامل مشاهده نسخه کامل : ایجاد try icon در ویژال سی



cpplover
01-01-2008, 00:43
با سلام
دوستان عزیز کسی نبود که به سوالات من پاسخ بده؟
خواهشمندم اگه دوستی میتونه منو راهنمایی کنه
ایجاد try icon در ویژال سی؟البته این کد های زیر این کار رو انجام میدن اما واسه ایجاد منو مشکل دارم





HICON hIcon;
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(IDR_MAINFRAM E),RT_GROUP_ICON);
hIcon = (HICON)LoadImage(hInst,MAKEINTRESOURCE(IDR_MAINFRA ME),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
NOTIFYICONDATA myicon;
myicon.hWnd=this->GetSafeHwnd();//
myicon.cbSize=sizeof(NOTIFYICONDATA);//
myicon.uFlags=NIF_MESSAGE | NIF_ICON | NIF_TIP;//
myicon.uCallbackMessage=IDD_AB_DIALOG;//
myicon.hIcon=hIcon;//
Shell_NotifyIcon(NIM_ADD,&myicon);//

m3hrz4d
01-01-2008, 04:59
شما باید پیغام هایی که برای اون Tray Icon فرستاده میشه رو بگیرین و مثلا وقتی روش کلیک میشه یک منو توی Position مناسب در جایی که موس هست نشون بدین.
پیغام های مربوط به این آیکن به پنجره با هندل ی که به ساختار NOTIFYICONDATA دادین فرستاده میشه که اینجا شما هندل شی فراخواننده رو دادین که مثلا فرض میکنیم MainFrame برنامه ی MFC شماست.پیغام هایی که فرستاده میشه مقدار uMsg شون همون فیلد uCallbackMessage هست که شما آیدی دیالوگ رو دادین که فکر نکنم درست باشه.
کاری که من برای گرفتن پیغام ها کردم اینه که اول یه پیغام Custom توی MainFrame.cpp تعریف کردم :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدو کدی که شما نوشته بودین رو اینطوری تغییر دادم :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدو توی مثلا OnCreate مربوط به MainFrame قرارش دادم.
بعد یک متد برای فراخوانیش هنگام گرفتن پیغام تعریف کردم. توی MainFrame.h :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدو توی MainFrame.Cpp :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
و توی MESSAGE_MAP هم این رو اضافه کردم :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا وقتی روی اون آیکون کلیک بشه یه MessageBox نشون داده میشه.
این تا این مرحله.
حالا شما میخواهین یه منو به جای MessageBox بگذارین.متاسفانه الان من عجله دارم ولی بگین مشکلتون در این مورد چیه و اصلا از یه روشی میخوایین استفاده کنین.
-
ضمن اینکه بهتره وقتی برنامه ی شما بسته میشه تابع Shell_NotifyIcon رو با مقدار NIM_DELETE برای حذف کردن اون آیکن فراخوانی کنین.

someone
01-01-2008, 10:50
سلام.
ممنون از دوست خوبم m3hrz4d و توضیحات کاملشون.

در این انجمن دو مقاله در مورد System Tray وجود دارد
که یکی مربوط به ایجاد اون در یک Win32App و دیگری مروبط به MFCApp میشه.
علاوه بر توضیحات دوست خوبم میتونین به دو لینک زیر مراجعه کنین :

1-
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

2-
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]


موفق باشین.

cpplover
01-01-2008, 16:03
سلام از جوابهای درخوری که دادید تشکر می کنم
ولی برنامه در این قسمت دچار مشکل میشه

LRESULT CMainFrame::OnSysTrayIconMessage(WPARAM wParam, LPARAM lParam)
{
if (WM_LBUTTONUP == lParam)
{
MessageBox(_T("Tray Icon Clicked!"));
}
return 0;
}
میشه راهنمایی بیشتری بدید؟
ممنون میشم

m3hrz4d
01-01-2008, 23:42
میشه بگین چه Error ی ؟ شما نمونه ی اولیه این متد رو در تعریف کلاس (MainFrame(MainFrame.h نوشتین؟
--
کاری که ما در کل میخواهیم بکنیم و بخاطریش این متد رو نوشتیم اینه که میخواهیم پیغام های خاصی که که پنجره ی MainFrame توسط Tray Icon فرستاده میشه رو بگیریم و عکس العمل مناسب رو انجام بدیم.
بنابراین این متد رو مینویسیم و با استفاده از قسمت MESSAGE_MAP به MFC میفهمونیم که وقتی پیغام مورد نظر به MainFrame فرستاده شد متد OnSysTrayIconMessage رو فراخوانی کن و مقادیر ارسال شده همراه پیغام (wParam و lParam) رو بهش بفرست.
بنابراین هر وقت اتفاقی برای Tray Icon ما بیافته مثلا روش کلیک بشه, یا موس روش حرکت کنه پیغام WM_SYSTRAYICON که در اون wParam و lParam حاوی نوع اتفاق هستن(مثلا توی کدی که نوشتم lParam نوع رویداد رو مشخص میکنه مثلا WM_LBUTTONDOWN برای فشرده شدن دکمه چپ موس)
و طبق چیزی که توی MESSAGE_MAP تعریف کردیم متد OnSysTrayIconMessage فراخوانی میشه و کدی که ما نوشتیم اجرا میشه.من کدی نوشتم که اگه دکمه سمت چپ زده شد یک MessageBox نشون بده.

cpplover
02-01-2008, 01:18
سلام دوست من



از اینکه تا این حد وقت میگذارید تا به سوالها جواب بدید واقعا خوشحالم و تشکر میکنم.



راستش اول باید چند تا سوال اساسی از شما بپرسم؟



1)آیا این چیزایی که گفتید واسه همه برنامه ها اعم ازتک سندی ،چند سندی ،ویا مبتنی بر کادر تبادلی صادقه؟
چون شما در خیلی جاها از mainframe صحبت کرده بودید در حالی که من mainframe رو در برنامه تک سندی پیدا کردم اما در dialog based نمی دونستم دقیقا باید کد رو کجا بگذارم (من واسه مبتنی بر کادر تبادلی میخوام. )

2)راستش من متوجه نشدم منظورتون از MESSAGE_MAP کجاست؟ میشه یه توضیح مختصر بدید؟

3) در خط :



HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(IDR_MAINFRAM E),RT_GROUP_ICON);



IDR_MAINFRAME دقیقا آی دی چیه؟ مثلا در DIALOG BASE


اما مشکلی که گفتم این بود:

خطای کامپایلر:

error C2039: 'OnSysTrayIconMessage' : is not a member of 'CMainFrame'

البته این هم شاید به این خاطره که من یکی از کد ها رو درست کپی نکرده باشم کلا در برنامه ای هم که دوست دیگری لینک داده بودند
برنامه کار می کرد اما یه فریم جدید ایجاد می شد و اشیایی رو که من در دیالوگ گذاشته بودم رو نمی شناخت

خیلی ممنون میشم اگه در مورد صحبت هایی که شد توضیح بدید .

m3hrz4d
02-01-2008, 02:12
*
میشه گفت روش کلی کار توی MFC توی DialogBased هم مثل همین هست . کل کاری که شما میکنین گرفتن یه پیغام هست که توی Dialog Basic هم روش همین هست منتها اونجا شما با یک شی مشتق شده از کلاس CDialog کار میکنین به جای MainFrame. منتها چون شما کدی که گذشتین توی MainFrame بود دیگه من تغییرش ندادم.
*
MESSAGE_MAP ی که ما باش کار داریم توی برنامه هایی که MainFrame دارین توی MainFrame.cpp هستن و توی Dialog Based ها توی Dialog Name]. cpp] هستش. یه جایی هست برای Dialog Based به این صورت :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
که جایی که Bold شده رو من برای کاری که میخواهیم بکنیم اضافه کردم
*
در خط :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدکاری که انجام میشه اینه که هندل اون Module ی که حاوی RESOURCE با آیدی IDR_MAINFRAME هست بدست میاد.
IDR_MAINFRAME اینطور که توی VS 2003 دیدم هم توی Single Document و هم توی Dialog Based (بقیه رو ندیدم) آیدی آیکنیه که توی پنجره ی اصلی نشون داده میشه.(میتونین از منوی View / Resource View ببینینش) که در حالت پیشفرض شکلش شکل آیکن MFC هست. در واقع اینجا برای Load کردن آیکن برای نمایشش, نیاز به داشتن Module Handle ی که این Resource داخلش هست داریم که با این کار پیداش میکنیم.البته فکر نکنم این کار خیلی ضروری باشه و بتونیم hInst رو با AfxGetInstanceHandle پیدا کنیم(Handle ماژول جاری) و توی خط بعد هم با تابع LoadImage اون آیکون رو از Resource لود میکنیم.
*
همونطور که توی پست قبلی هم گفتم شما متد OnSysTrayIconMessage رو که برای MainFrame یا Dialog تون توی MainFrame.cpp یDialogName].cpp] پیاده سازی کردین توی قسمت اعلان کلاس یعنی فایل MainFrame.h یا DialogName].h] اضافه نکردین. مثلا توی DialogName].h] :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدکه جایی که Bold شده رو من برای کاری که میخواهیم بکنیم اضافه کردم.
خود خطا هم میگه که متد OnSysTrayIconMessage برای کلاس تعریف نشده و عضو کلاس نیست.

someone
02-01-2008, 02:44
سلام.

با عرض عذرخواهی از m3hrz4d به خاطر کنجکاوی من
و کسب اجازه از ایشون ، بابت پاسخ دادن به سوالات.


1- برنامه های Dialog based فاقد کلاس CMainframe هستند.
اگه دقت کردن باشین در برنامه های SDI , MDI شما ، شمای پروژه که همون فریم اصلی برنامه هست رو
در Resource ها نمیبینین. دلیلش اینه که این پنجره به صورت Run-Time ایجاد میشه.
(با استفاده از WNDCLASS structure)
CMainFrame برای نگه داری منو و نوار ابزار و نوار وظیفه استفاده میشه.


2- فرض میکنیم شما یک پروژه ی Dialog based دارید.
در کلاس Dialog و در فایل Cpp اون بخش زیر رو پیدا کنین :



برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

بخشی از کد رو که با رنگ قرمز مشخص کردم مربوط به بررسی پیغام ها در کلاس Dialog هست.
و خطی که با رنگ آبی مشخص کردم محل قرار گرفتن کدی هست که دوستمون گذاشتن.
و اما یه توضیح مختصر :
همونطر که میدونین اساس کار ویندوز بر پردازش پیام هایی که از کاربر دریافت میکنه قرار داره.
مثلا وقتی شما روی یک Button کلیک میکنین پیغامی به پنجره مورد نظر فرستاده میشه. این پیغام یک
عدد میتونه باشه. وقتی مترجم پیغام ها (TranslateMessage) به این عدد میرسه اونرو با استفاده از ماکروهایی
مثل ON_MESSAGE ، به تابعی که باید در هنگام دریافت عدد مورد نظر فعال بشه ، فرمان اجرا شدن رو میده.
(البته من به صورت کلی عرض کردم و جزییات پیچیده تر و کمی متفاوت تر هست)

برای اینکه منظور من رو بهتر متوجه بشین ، Button ی رو به برنامه اضافه کنین و برای استفاده از اون
روش دوبار کلیک کنین. بلافاصله به MassgeMap مراجعه کنین. کد زیر به اون اضافه میشه :


برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

یعنی وقتی که Button1 فشرده شد ، تابع OnBnClickedButton1 رو فراخوانی کن.
و همین طور در مورد قرار گرفتن موس بر روی Tray


3-
کافیه یه پروژه ی SDI و یا MDI ایجاد کنین و برگه Resource رو باز کنین. حتما با IDR_MAINFRAME
مواجه میشین. که شامل ID آیکن برنامه و همینطور منو و شتاب دهنده ی اون هست.
دوستمون برای اینکه از آیکن خود برنامه استفاده کنن ، نیاز به handle خود برنامه دارن. با استفاده از
AfxFindResourceHandle این handle رو استخراج کردن و سپس با رد کردن اون به تابع loadimage ، آیکن
اصلی برنامه رو در اختیار گرفتن.

cpplover
02-01-2008, 10:15
با سلام و عرض پوزش:



راستش من این کارها روانجام دادم اما نمی دونم چرا باز هم دچار خطا های زیر در برنامه شدم (شاید به خاطر تازه کار بودنه!)



1)همونطوری که گفتید :



#define WM_SYSTRAYICON WM_USER + 0x100


رو در[dialogname].cpp کپی کردم .

2)کدهای قسمت دوم رو هم در دو جا تست کردم :

هم در onpaint() و هم در OnInitDialog
که از اونها هم خطایی گرفته نمیشه

بقیه کد ها رو هم طوری که گفته بودید (با تشکر از حسن دقت شما) کپی کردم

اما با دو خطا مواجه میشم که در قسمت زیر وجود داره :


LRESULT CMainFrame::OnSysTrayIconMessage(WPARAM wParam, LPARAM lParam)
{
if (WM_LBUTTONUP == lParam)
{
MessageBox(_T("Tray Icon Clicked!"));
}
return 0;
}

}


1) error C2653: 'CMainFrame' : is not a class or namespace name


2) error C2660: 'MessageBoxA' : function does not take 1 parameters


به قول شما دیگه داره خدمونی میشه:20:

از دوست خوبمون آقای someone هم به خاطر توضیحاتشون کمال تشکر رو دارم

m3hrz4d
02-01-2008, 12:04
سلام.

با عرض عذرخواهی از m3hrz4d به خاطر کنجکاوی من
و کسب اجازه از ایشون ، بابت پاسخ دادن به سوالات.


1- برنامه های Dialog based فاقد کلاس CMainframe هستند.
اگه دقت کردن باشین در برنامه های SDI , MDI شما ، شمای پروژه که همون فریم اصلی برنامه هست رو
در Resource ها نمیبینین. دلیلش اینه که این پنجره به صورت Run-Time ایجاد میشه.
(با استفاده از WNDCLASS structure)
CMainFrame برای نگه داری منو و نوار ابزار و نوار وظیفه استفاده میشه.


2- فرض میکنیم شما یک پروژه ی Dialog based دارید.
در کلاس Dialog و در فایل Cpp اون بخش زیر رو پیدا کنین :



برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدبخشی از کد رو که با رنگ قرمز مشخص کردم مربوط به بررسی پیغام ها در کلاس Dialog هست.
و خطی که با رنگ آبی مشخص کردم محل قرار گرفتن کدی هست که دوستمون گذاشتن.
و اما یه توضیح مختصر :
همونطر که میدونین اساس کار ویندوز بر پردازش پیام هایی که از کاربر دریافت میکنه قرار داره.
مثلا وقتی شما روی یک Button کلیک میکنین پیغامی به پنجره مورد نظر فرستاده میشه. این پیغام یک
عدد میتونه باشه. وقتی مترجم پیغام ها (TranslateMessage) به این عدد میرسه اونرو با استفاده از ماکروهایی
مثل ON_MESSAGE ، به تابعی که باید در هنگام دریافت عدد مورد نظر فعال بشه ، فرمان اجرا شدن رو میده.
(البته من به صورت کلی عرض کردم و جزییات پیچیده تر و کمی متفاوت تر هست)

برای اینکه منظور من رو بهتر متوجه بشین ، Button ی رو به برنامه اضافه کنین و برای استفاده از اون
روش دوبار کلیک کنین. بلافاصله به MassgeMap مراجعه کنین. کد زیر به اون اضافه میشه :


برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدیعنی وقتی که Button1 فشرده شد ، تابع OnBnClickedButton1 رو فراخوانی کن.
و همین طور در مورد قرار گرفتن موس بر روی Tray


3-
کافیه یه پروژه ی SDI و یا MDI ایجاد کنین و برگه Resource رو باز کنین. حتما با IDR_MAINFRAME
مواجه میشین. که شامل ID آیکن برنامه و همینطور منو و شتاب دهنده ی اون هست.
دوستمون برای اینکه از آیکن خود برنامه استفاده کنن ، نیاز به handle خود برنامه دارن. با استفاده از
AfxFindResourceHandle این handle رو استخراج کردن و سپس با رد کردن اون به تابع loadimage ، آیکن
اصلی برنامه رو در اختیار گرفتن.
ممنون به خاطر توضیحاتتون

m3hrz4d
02-01-2008, 12:15
با سلام و عرض پوزش:
راستش من این کارها روانجام دادم اما نمی دونم چرا باز هم دچار خطا های زیر در برنامه شدم (شاید به خاطر تازه کار بودنه!)
1)همونطوری که گفتید :
#define WM_SYSTRAYICON WM_USER + 0x100
رو در[dialogname].cpp کپی کردم .

2)کدهای قسمت دوم رو هم در دو جا تست کردم :

هم در onpaint() و هم در OnInitDialog
که از اونها هم خطایی گرفته نمیشه

بقیه کد ها رو هم طوری که گفته بودید (با تشکر از حسن دقت شما) کپی کردم

اما با دو خطا مواجه میشم که در قسمت زیر وجود داره :


LRESULT CMainFrame::OnSysTrayIconMessage(WPARAM wParam, LPARAM lParam)
{
if (WM_LBUTTONUP == lParam)
{
MessageBox(_T("Tray Icon Clicked!"));
}
return 0;
}

}


1) error C2653: 'CMainFrame' : is not a class or namespace name


2) error C2660: 'MessageBoxA' : function does not take 1 parameters


به قول شما دیگه داره خدمونی میشه:20:

از دوست خوبمون آقای someone هم به خاطر توضیحاتشون کمال تشکر رو دارم

اینطور که شما گفتین با Dialog سرو کار کارین پس کلاس Dialog شما یه چیزی به صورت :

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید هستش در صورتی که شما بجاش CMainFrame گذاشتی که در پروژه ی Dialog Based ما باهاش کاری نداریم و برنامه ی ما حول یک کلاس مشتق شده از CDialog میچرخه. برای مثال برای من اینطوری هست:

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدبا حل این مشکل احتمالا مشکل دوم حل میشه اگه نشد(که خیلی بعیده) قبل از MessageBox یک CWnd بگذارین(سریحا از متد MessageBox مربوط به کلاس CWnd استفاده میشه)

برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید

cpplover
02-01-2008, 23:04
با تشکر از شما که تا این حد من رو راهنمایی کردید در نهایت برنامه جواب داد:40:
اما ادامه موضوع رو با اجازه در یک تایپیک دیگه میارم که امیدوارم اونجا هم کمکم کنید