علی محمد‌ حسین‌ زاده چهارشنبه 3 اردیبهشت 1393 07:15 بعد از ظهر نظرات ()
یکی از مشکلاتی که برنامه نویسان ویژوال فاکس پرو ممکن است با آن مواجه شوند، چاپ محتوای کنترل درخت/Tree خواهد بود. در این مقاله سعی میکنم تا راههایی را در راستای حل این مشکل ارائه دهم.
پیشاپیش از نظرات سازنده شما خواننده محترم برای کامل کردن روشهای زیر استقبال می کنم.

مقدمات
برای این مقاله جدولی بنام groups را با ساختار زیر در نظر میگیریم:
Autoinc id
Integer g_id
Charactername
این یک ساختار استاندارد با حداقل  تعداد فیلد است که در تصویر زیر نمونه اطاعاتی که در مثالمان استفاده کرده ایم را میتوانبد مشاهده کنید :
اطلاعات جدول گروه
در اینجا توضیح اندکی راجع به نحوه نمایش این اطلاعات در شئ 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 استفاده شود.

در ادامه نمونه تولید شده توسط گزارش را مشاهده میکنید:


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

منبع : بخش مقالات وب سایت برنامه های بی نیاز
تاریخ نگارش مقاله : 1387/11/28