چاپ رکورد جاری توسط FastReport

اگر می‌خواهید که توسط FastReport در یک جدول فقط رکورد جاری را چاپ کنید و بجای رکورد جاری، رکورد اول و یا همه‌ی رکوردها چاپ می‌شوند به احتمال زیاد کامپوننت‌های FastReport بر روی فرمی که درحال کار با آن هستید قرار دارد.
ممکن است بخواهید از قطعه کد زیر برای این منظور استفاده کنید ولی این روش هم جواب نمی‌دهد:
frxDBDataset.RangeBegin := rbCurrent;
frxDBDataset.RangeEnd := reCurrent;
frxReport.ShowReport;

راه حل آن این است که تمامی کامپوننت‌ها FastReport را به یک DataModule منتقل کرده و برای چاپ یک وهله از این DataModule را ایجاد کرده و اقدام به چاپ نمایید. در این حالت مشکل چاپ رکورد جاری وجود نخواهد داشت.

ترسیم کاراکتر به کاراکتر یک رشته فارسی در صفحه

Persian Type Tutor را که خاطرتان هست، قرار بود که در مورد بخش‌های مختلف آن توضیحاتی را ارائه کنم.

یکی از مواردی که در این نرم‌افزار استفاده شده، نمایش متنی است که کاربر قراراست آن را تایپ کند. به این صورت که این متن به رنگ مشکی در صفحه نمایش داده می‌شود و با تایپ کردن هر حرف از متن آن حرف به رنگ زرد رنگ در خواهد آمد و همچنین یک نشانگر به صورت چشمک‌زن در زیر حرف بعدی که قراراست تایپ شود نمایش داده می‌شود.

مسئله‌ای که وجود دارد نمایش حروف یک کلمه فارسی به صورت رنگی می‌باشد.
حتماً می‌پرسید چه مسأله‌ای؟
در ادامه یک توضیح در مورد حروف فارسی:
همانطور که می‌دانید بعضی از حروف فارسی با توجه به موقعیت آن در کلمه به شکل‌های مختلف نمایش داده می‌شود. به عنوان مثال حرف «س» را در کلمات زیر در نظر بگیرید:
 
Persian Type Tutor Image 1
 
این حرف با توجه به اینکه در اول، وسط و یا آخر کلمه باشد شکل‌های مختلفی به خود گرفته است.
حال قطعه کد زیر را در نظر بگیرید:


const
  Str = 'تست';
var
  I: Integer;
  XPos: Integer;
begin
  XPos := 400;
  for I := 0 to Length(str) - 1 do
  begin
    TextOut(Canvas.Handle, XPos, 10, @Str[I+1], 1);
    XPos := XPos - Canvas.TextWidth(Str[I+1]);
  end;
end;

می‌خواهیم کلمه‌ی «تست» را بصورت حرف به حرف در صفحه ترسیم کنیم. خروجی ای قطعه کد چیزی شبیه به این خواهد بود:

Persian Type Tutor Image 2

 
همانطور که می‌بینید حروف تماماً‌ بصورت غیر متصل در صفحه ترسیم شده‌اند. داستان از چه قرار است؟

وقتی که شما توسط یک دستور ترسیم، رشته‌ای را در صفحه ترسیم می‌کنید سیستم عامل در پس پرده با توجه به فونت انتخابی صفحه ترسیم (Canvas) و با توجه به موقعیت هر حرف در کلمه شکل مخصوص به آن حرف (گلایف) را از جدول فونت مربوطه استخراج کرده و در صفحه ترسیم می‌نماید.

من چطور این ترسیم را انجام دهم؟

کل کار با استفاده از دو تابع API ویندوز انجام می‌شود: 
GetCharacterPlacementW:جهت استخراج خصوصیات کاراکترهای رشته.
ExtTextOutW: جهت ترسیم رشته در صفحه.

و اما نحوه استفاده:
ابتدا رکورد زیر را تعریف می‌نماییم:

type
 
  PIntArray = array of Integer;
  PwcArray  = array of widechar;
 
  WideCharInfo = Record
    lpDx: PIntArray;
    lpGlyphs: PwcArray;
    lpOrder: PIntArray;
  End;


lpDx: آرایه‌ایست که در آن عرض گلایف مربوط به کاراکترهای رشته قرار می‌گیرد که از آن برای تعیین موقعیت ترسیم هر گلایف در صفحه (و یا نمایش نشانگر چشمک‌زن زیر کاراکترها) استفاده خواهیم کرد.
lpGlyphs: در این آرایه کد یونیکد هر گلایف قرار داده می‌شود.
lpOrder: در این آرایه هم شماره ترتیب هر گلایف در رشته قرار داده می‌شود. (این حالت برای زبان‌های راست به چپ استفاده دارد)
سپس توسط تابع زیر اطلاعات مربوط به رشته‌ای را که قصد ترسیم آن را داریم را استخراج می‌نمائیم:

function GetCharacterPlace(DC: HDC;
    sText:  WideString): WideCharInfo;
var
  GCP       : TGCPResults;
  TextLength: Integer;
begin
 
  TextLength := Length(sText);
 
  SetLength(Result.lpOrder, TextLength);
  SetLength(Result.lpDx, TextLength);
  SetLength(Result.lpGlyphs, TextLength);
 
  GCP.lStructSize := sizeof(TGCPResults);
  GCP.lpOutString := nil;
  GCP.lpOrder := Pointer(Result.lpOrder);
  GCP.lpDx := Pointer(Result.lpDx);
  GCP.lpGlyphs := Pointer(Result.lpGlyphs);
  GCP.lpCaretPos := nil;
  GCP.lpClass := nil;
  GCP.nGlyphs := TextLength;
  GCP.nMaxFit := 0;
 
  GetCharacterPlacementW(DC, Pointer(sText), TextLength, 0,
    GCP, GetFontLanguageInfo(DC))
 
end;

و در آخر نحوه ترسیم رشته در صفحه با استفاده از تابع بالا:

procedure DrawPersianText(Canvas: TCanvas; Str: WideString);
var
  aRect     : TRect;
  CharInfo  : WideCharInfo;
  Options   : LongInt;
  wChar     : widechar;
  I         : Integer;
  xPos      : Integer;
begin
 
  aRect := Canvas.ClipRect;
  CharInfo := GetCharacterPlace(Canvas.Handle, Str);
 
  xPos := aRect.Right - 100;
  Options := ETO_GLYPH_INDEX;
 
  I := 0;
  while I < Length(Str) do
  begin
    if (I mod 2) = 0 then
      Canvas.Font.Color := clBlack
    else
      Canvas.Font.Color := clRed;
 
    wChar := CharInfo.lpGlyphs[CharInfo.lpOrder[I]];
    xPos := xPos - CharInfo.lpDx[CharInfo.lpOrder[I]];
    ExtTextOutW(Canvas.Handle, xPos, 10, Options, @aRect, @wChar, 1, nil);
    Inc(I);
  end;
end;
 
procedure TfrmMain.FormPaint(Sender: TObject);
Const
  Str = 'تست';
begin
  DrawPersianText(Canvas, Str);
end;
که خروجی آن به صورت زیر خواهد بود:

 

Persian Type Tutor Image 3


دریافت سورس کد مثال:


برای مشاهده مثال کامل به سورس کد Persian Type Tutor مراجعه فرمائید.
همچنین اطلاعات بیشتر در مورد تابع GetCharacterPlacementW

 

فعال شدن خودکار زبان انگلیسی

نرم‌افزاری را توسط Delphi Xe2 ایجاد کرده‌ام که در در موقع اجرا زبان فارسی را فعال می‌کرد. ولی در حین کارکردن گاهگاهی زبان انگلیسی به صورت خودکار فعال می‌شد که واقعاً عذاب آور بود.

مشکل در کجاست؟

مشکل زمانی رخ می‌دهد که شما از کنترل DbGrid و یا کنترل‌های دیگری که از TCustomGrid دلفی مشتق شده باشند در فرم خود استفاده کرده‌‌اید.

راه حل:

در فایل Vcl.Grids و در خط 7144 قطعه کد زیر وجود دارد
if HWND(Message.FocusedWnd) &lt;&gt; Grid.Handle then
   ActivateKeyboardLayout(Screen.DefaultKbLayout, KLF_ACTIVATE);


در این قطعه کد مشخص نیست که به چه علت پس از خروج فوکوس از DbGrid زبان پیش‌فرض سیستم فعال می‌شود.

این دو خط را غیرفعال کرده و فایل را ذخیره کنید. سپس از مسیر Project --> add to project این فایل را به پروژه خود اضافه کنید.

نرم‌افزار متن‌باز Persian Type Tutor


Persian Type Tutor

نرم‌افزار PersianTypeTutor نرم‌افزار آموزش تایپ ده‌انگشتی فارسی و انگلیسی است که آخرین نسخه آن را می‌توانید از آدرس زیر دانلود کنید:
 
دریافت آخرین نسخه:
 
دریافت سورس‌کد نرم‌افزار:
 
این نرم‌افزار توسط RAD Studio XE2 پیاده‌سازی شده‌است.