ProgressCtrl

yair24

Member
ProgressCtrl

שלום, יש לי תוכנית שמבצעת 8 פעמים פעולה מסוימת שלוקחת משהו כמו חצי שניה, בגלל שזה 8 פעמים חצי שניה זה לוקח משהו כמו 4 שניות לעשות את הפעולה הזאת אז רציתי לשים PROGRESSBAR שיראה למשתמש את התקדמות הפעולה. זה הקוד:
void CDialogDlg::OnTran() { int i; CByteArray a,b,c,d,e,f,g,h,head; head.Add(72); // add header byte! for(i=0;i<480;i++) // add 1st 10 bytes { a.Add(hexarray); // data bytes b.Add(hexarray[i+480]); // data bytes c.Add(hexarray[i+960]); // data bytes d.Add(hexarray[i+1440]); // data bytes e.Add(hexarray[i+1920]); // data bytes f.Add(hexarray[i+2400]); // data bytes g.Add(hexarray[i+2880]); // data bytes h.Add(hexarray[i+3360]); // data bytes } m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(head)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(a)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(b)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(c)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(d)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(e)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(f)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(g)); m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(h)); m_progCtrl.StepIt(); m_progCtrl.SetPos(0); }

הבעיה היא שהבר עולה אבל לא בצורה רציפה אלא בקפיצות לא יפות... יש דרך להקפיץ את הבר בצורה רציפה? יאיר
 

yair24

Member
הוספתי עכשיו

זה נראה קצת יותר טוב אבל עדיין זה קופץ בצעדים גדולים... נראה לי שאני צריך באיזושהי דרך להוסיף לו עוד צעדים ולא רק 8 פעמים... יאיר
 

galh

New member
תרמה... ../images/Emo13.gif

תגדיל, נניח פי 100, את טווח הערכים, ובמקום StepIt אחד, תעשה 10.
 

yair24

Member
עדיין לא יפה, הנה הקוד:

void CDialogDlg::OnTran() { int i; CByteArray a,b,c,d,e,f,g,h,head; head.Add(72); // add header byte! for(i=0;i<480;i++) // add 1st 10 bytes { a.Add(hexarray); // data bytes b.Add(hexarray[i+480]); // data bytes c.Add(hexarray[i+960]); // data bytes d.Add(hexarray[i+1440]); // data bytes e.Add(hexarray[i+1920]); // data bytes f.Add(hexarray[i+2400]); // data bytes g.Add(hexarray[i+2880]); // data bytes h.Add(hexarray[i+3360]); // data bytes } for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(head)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(a)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(b)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(c)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(d)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(e)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(f)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(g)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_Comm.SetOutput(COleVariant(h)); for(i=0;i<10;i++) m_progCtrl.StepIt(); m_progCtrl.SetPos(0); }

האם זה אפשרי לעשות את זה בTHREAD נפרד? יאיר
 

galh

New member
אפשרי תמיד, השאלה אם כדאי.

אני מניח השורה: m_Comm.SetOutput(COleVariant(h)); היא קריאה לפונקציה "חוסמת" שגורמת לכך שה- progressbar נתקע, אני צודק?
 

yair24

Member
כן

זה פונקציה שמשדרת מערך של 480 בתים דרך הRS232 ולא אני כתבתי את הפונקציה הזו אז אני לאל יכו להיכנס אליה ולהעלות את הPROGRESSBAR בתוכה...
 

yair24

Member
בוא נדבר על THREADS

נגיד אני רוצה לשים את הPROGRESSBAR בתוך THREAD, אני מנסה לחשוב איך עושים את זה ונתקע. חשבתי על רעיון כזה: תהיה לי פונקציה שמריצה את הPROGRESSBAR בתוך לולאת FOR, הפונקציה הזו תרוץ בTHREAD, ובכל איטרציה היא תבדוק משתנה דגל. ברגע שהדגל יהיה בSET הTHREAD יסתיים. בינתיים הפונקציה הראשית זאת שהפעילה את הTHREAD תשלח את הבתים בRS232. מתי הדגל יהיה בSET? כמובן אחרי שהפונקציה הראשית גמרה לשלוח את כל המידע בRS232, אז היא תשנה את הערך של הדגל וזהו. עכשיו לשאלות: האם זאת הדרך לעשות את מה שאני רוצה? האם אחרי קריאה לפונקציה שמתחילה את הTHREAD אני יכול לשים עוד קוד? והוא ירוץ ביחד עם הTHREAD? יאיר
 

yair24

Member
בקשר לשאלה השניה

אני מסתכל עכשיו בתוכניות עם דוגמאות לTHREADS ואני לא ראיתי שום תוכנית שמישהו כותב קוד אחרי השורה של ה
AfxBeginThread(SecThreadProc, GetSafeHwnd(), THREAD_PRIORITY_NORMAL);​
אבל זה מה שאני צריך לעשות, אני צריך להתחיל את הTHREAD של הPROGRESSBAR ואז לטפל בבתים שנשלחים דרך הCOM. אני יכול? או לא יכול, לכתוב קוד אחרי הפונקציה שמתחילה את הTHREAD? אם לא אז איך בכל זאת אני עושה את זה? הרי בטוח יש דרך לעשות את זה לא...?
 

galh

New member
בטח שיש.

יוצרים thread במצב suspended (הכי פשוט ע"י CWinThread), משנים לו ת'הגדרות ואז מריצים אותו עם Run. לדעתי עדיף לך שמי שישב ב- thread נפרד יהיה החלק ששולח ת'נתונים ואת ה- progress bar ואת העדכון שלו תשאיר ב- thread של האפליקציה. "תחלק" את ה- bar לחלקים (לפי מספר השליחות ל- RS-232). ה- bar מתעדכן ע"י הודעות WM_TIMER עד לכל חלק. ברגע שה- RS-232 סיים הוא שולח הודעה או event (אירוע בלעז) ואז ה- bar "רץ" קצת יותר מהר בשביל להגיע לסוף החלק. אני חושב שזה יתן לך את התנועה הכי חלקה (בלי להסתבך יותר מידי).
 

galh

New member
לא.

אמרתי לך, אני מעדיף שה- GUI ישב ב- thread אחד בלבד.
 

yair24

Member
אוקי יש לי עוד שאלה

בשביל לשדר החוצה אני משתמש באובייקט של CMsComm איך אני מעביר את המופע שלו לTHREAD? אני צריך אותו בשביל לשדר החוצה את הRS232...
 

galh

New member
שתי אפשרויות.

member בתוך CWinThread שמחזיק מצביע ל- mscomm. או להעביר את המצביע בתור הפרמטר ל- thread function.
 

yair24

Member
יפה זה בדיוק מה שעשיתי

void CDialogDlg::OnTran() { UpdateData(TRUE); COMMWND *pr=new COMMWND; // each window that we create a handle is been created pr->hwnd=GetSafeHwnd(); // automaticly by MFC, this func get the handle. // its safer to send the handle then the MFC object. pr->m_Comm=&m_Comm; AfxBeginThread(transcom,pr); // Eratho is a pointer to the function that handle the thread.​
הבעיה שכשאני מריץ את התוכנית היא מתרסקת...
 

yair24

Member
יצא לא טוב

אני משרשר במקום אחר כדי להגדיל את החלון.
 

yair24

Member
יכול להיות שזה בגלל

שהמשתנה MEMBER שנקרא m_Comm מקושר לACTIVEX MSCOMMCTRL6 שפעם אמרת לי לא להשתמש בו? יאיר
 

yair24

Member
גל כנס לפה!!

הנה השורה שמעבירה את המצביע לMSCOMM לTHREAD
pr->m_Comm=&m_Comm;​
 

galh

New member
להכנס לאן? ../images/Emo12.gif

מה הסוג (type) של שני המשתנים?
 

yair24

Member
../images/Emo13.gif

המשתנה ששיך למחלקה ומקושר לפקד טלפון הוא מסוג:
CMSComm m_Comm;​
ועכשיו הגדרתי עוד STRUCT שמחזיק מצביע לחלון שאני אקרא לו עם GETSAFEWND פלוס מצביע לMSCOMM שאליו אני עושה השמה למצביע של המשתנה שלמעלה והמבנה הזה מוגדר ככה:
typedef struct { HWND hwnd; CMSComm *m_Comm; }COMMWND;​
את המבנה הזה אני מעביר כשאני קורא לפונקציה AFXBEGINTHREAD (זה הPAVAR שאינ מעביר לפונקציה של הTHREAD)
 
למעלה