در اينجا توضيح اندکي راجع به نحوه نمايش اين اطلاعات در شئ Tree خواهيم داشت . يک فرم ساخته و با انتخاب گزينه ActiveX Control يک شئ Microsoft TreeView Control را روي فرم قرار ميدهيم و بنام
oTree تغيير نام ميدهيم . سپس در متد Init آن کد زير را مينويسيم :
Select groups
Go Top
Set Filter To g_id=0
Scan
This.oTree.Nodes.Add(,1,"g"+Alltrim(Str(groups.Id)),Alltrim(groups.Name))
Endscan
Set Filter To
Go Top
همچنين کد زير را در متد NodeClick شئ oTree قرار دهيد :
Local ParentId
If Not Isnull(This.SelectedItem)
Thisform.nodekey=Alltrim(Node.Key)
Thisform.pageframe1.page1.txtParent.Value=Alltrim(Node.Text)
Thisform.pageframe1.page2.txtName.Value=Alltrim(Node.Text)
ParentId=Right(Node.Key,Len(Node.Key)-1)
Select groups
Set Filter To g_id=Val(ParentId)
If Node.children=0
Scan
This.Nodes.Add(Node.Key,4,"g"+Alltrim(Str(groups.Id)),Alltrim(groups.Name))
Endscan
Endif
Set Filter To
Go Top
Endif
به اين ترتيب شما با کليک بر روي هر گره پدر در صورت وجود فرزندان آن به درخت اضافه ميشوند . حال شما يک Tree داريد که ميخواهيد امکان چاپ محتويات آن را به کاربر بدهيد.
تبديل
ساده ترين راه چاپ خود شئ درخت هست . يعني تلاش کنيم تا چارچوب اين کنترل
را در يک فايل گرافيکي ذخيره کنيم وآن را چاپ کنيم .همين چاپ کردن باز به
طرق مختلف قابل انجام هست که در ادامه به شرح کامل اين روش ميپردازيم.
جهت تبديل اين چارچوب به يک فايل گرافيکي نياز به برنامه اي داريم تا بتواند با دريافت دستگيره (handle) شئ oTree آن را تبديل کند ، اگر از ويرايش 9.0 ويژوال فاکس پرو استفاده ميکنيد ميتوانيد از کتابخانه قدرتمند
GDIPlusX استفاده کنيد ما در اين مقاله از کلاس
GPImage استفاده ميکنيم و دليل آن اينست که اين کلاس در ويرايش هاي 6.0 تا 9.0 ويژوال فاکس پرو قابل استفاده است.
ما از کد زير براي تبديل و نمايش فايل گرافيکي استفاده ميکنيم :
#include gpImage.h
LOCAL fname
fname=GETENV("TEMP")+"_"+SUBSTR(SYS(2015), 4)+".jpg"
DECLARE INTEGER ShellExecute IN SHELL32 INTEGER, STRING, STRING, STRING, STRING, INTEGER
IF NOT "gpImage" $ SET("Procedure")
SET PROCEDURE TO gpImage ADDITIVE
ENDIF
gdip = CREATEOBJECT("gpInit")
img = CREATEOBJECT("gpImage")
img.Capture(THISFORM.otree.HWND)
img.SaveAsJPEG(fname)
RELEASE img
RELEASE gdip
ShellExecute(0,"open",fname,"","",1)
در توضيح کد بالا اينکه در خط اول فايل حاوي تعاريف مورد نياز کلاس gpimage در برنامه وارد ميشود در خط بعد يک متغيير محلي براي ذخيره نام فايل تعريف شده و در خط بعد مقدار دهي ميشود.
در خط چهارم تابع ويندوزي ShellExecuteفراخواني ميشود . سپس يک نمونه از کلاس گرافيکي ساخته شده و همينطور يک نمونه از کلاس تصوير بعد از آن با اعلام هندل شئ به متد Capture شئ تصوير ، تصوير آن توليد ميشود و به فرمت Jpeg ذخيره ميکنيم و نمونه ها را از حافظه پاک ميکنيم در نهايت هم با استفاده از تابع ويندوزي آن را نمايش ميدهيم.
اين شرح کلي کد بالا است شايد اينجا اين سئوال مطرح شود که چرا از تابع ShellExecute استفاده شده است؟ در جواب بايد گفت که با اين انتخاب ميتوان چنديد هدف را زد :
اول اينکه اين تابع برنامه اي را که در ويندوز وظيفه نمايش اين نوع فايل را بر عهده دارد را صدا ميزند و ما از بابت نمايش آن خيالمان آسوده است و
دوم اينکه با تغيير دستور بالا به شکل زير ميتوان آن تصوير را مستقسم به چاپگر فرستاد بدور از دغدغه تغيير اندازه و يا کيفيت آن البته از همان کلاس گرافيکي نيز ميتوان استفاده کرد :
ShellExecute(0,"print",fname,"","",1)
اين يکي از راههاي چاپ تصوير بود راه ديگر اين است که اگر شما بخواهيد متني و يا اطلاعاتي اضافه را نيز به همراه آن چاپ کنيد ميتوانيد يک کرسر با يک فيلد General بسازيد و از دستور زير استفاده کرده و محتويات آن فايل را به جدول اضافه کنيد تا بتوانيد در گزارش خود با استفاده از يک فيلد تصوير آن را نمايش و چاپ کنيد :
APPEND GENERAL GeneralFieldName [FROM FileName]
[DATA cExpression] [LINK] [CLASS OLEClassName]
اما شايد شما هم به مشکل من بخورد کنيد ، به تصاوير زير دقت کنيد :
همانطور که ملاحظه ميکنيد مشکل زماني پيش مي آيد که شئ Tree ما داراي Scroll bar بشود وغير از برنامه هاي مخصوص اين کار مانند Snag It چاره ديگري براي تبديل کامل آن به فايل گرافيکي نيست ، براي حل اين مسئله راه حل دوم را مطرح ميکنيم.
اطلاعات
در اين راه حل سعي ميکنيم تا به نحو خاصي اطلاعات را در يک کرسر ديگر بريزيم که بتوانيم توسط يک گزارش معمولي در ويژوال فاکس پرو چاپي همانند Tree را شبيه سازي کنيم خاصيت اين روش برداشته دشن قيد محدوديت رکوردها است براي اين کار از کد زير استفاده ميکنيم :
Use Locfile("groups","dbf")
ret_tree(0,0)
Select test
Report Form report2 Preview
Function ret_tree(p_id,k)
Local i,j,larr[1,3],rnum
Select * From groups Where g_id=p_id Into Cursor tmp
rnum=Reccount()
If rnum>0
Dimension larr[rnum,3]
j=1
Scan
larr[j,1]=tmp.Id
larr[j,2]=tmp.Name
larr[j,3]=tmp.g_id
j=j+1
Endscan
Endif
Use
If rnum>0
k=k+3
For i=1 To rnum
Insert Into test (Name) Values (Alltrim(larr(i,2))+Replicate(" ",k)+".")
ret_tree(larr(i,1),k)
Endfor
Endif
Endfunc
در اين کد با استفاده از يک تابع بازگشتي هر شاخه از درخت را پيمايش کرده و بترتيب آنها را در يک کرسر که تنها حاوي يک فيلد کاراکتري است ذخيره ميکنيم و يک گزارش ساده تنها با يک فيلد که متصل به کرسر است را صدا ميزنيم ، اما نکته اصلي در دستور insert است که ما در هر پله متناسب با آن مقداري فضاي خالي به رشته اضافه ميکنيم تا بتوانيم شبيه سازي خود را کامل کنيم البته شما با تغيير مقدار اضافه شده به متغيير k ميتوانيد طول فاصله را به ميل خود تغيير دهيم.
اما سئوالي که ممکن است مطرح شود اين است که چرا از آرايه استفاده کرده ايم؟ توضيح اينکه در ويژوال فاکس پرو در يک تابع بازگشتي همانند متغييرها نميتوان از جداول استفاده کرد اما مثلا در php اين امکان هست و اين برميگردد به اصول ويژوال فاکس پرو که هر جدول در يک ناحيه کاري باز ميشود و اگر بخواهيم از آن استفاده کنيم هر مرحله فقط همان جدول اوليه را داريم حتي اگر از دستور Create Cursor استفاده شود.
در ادامه نمونه توليد شده توسط گزارش را مشاهده ميکنيد :

جهت مشاهده عکس ها در اندازه واقعي روي آنها کليک کنيد