Category Archives: Delphi

Memperkecil ukuran EXE pada Delphi

Bismillahirrohmanirrohim.
Assalamu’alaikum wr wb.
Delphi versi lebih baru hadir dengan beberapa kemudahan dan kelebihan diantara beberapa komponen yang sebelumnya harus menambahkan secara manual yang mana hal tersebut terkadang tidak mudah bagi pemula, saat ini hanya dengan menginstall Delphi 10.3 Rio Community Edition kita sudah dapat membuat aplikasi yang bagus tanpa repot-repot menambahkan komponen pihak ketiga.
Namun dibalik kemudahan dan kelebihannya disisi lain ada yang membuat sedikit kurang yaitu ukuran EXEnya yang lumayan gendut, beberapa teman di media sosial yang sebelumnya menggunakan Delphi 7 keluhannya “bisa gak sih ukuran EXEnya diperkecil” saat mencoba menggunakan Delphi versi yang lebih baru.
Pada artikel kali ini saya akan mencoba menjawab keluhan teman-teman (termasuk saya juga dulu).
Kalo diperkecil segede EXEnya Delphi 7 sepertinya sulit, tapi kalo sedikit dirampingkan bisa dengan langkah-langkah dibawah ini.
Ada beberapa langkah untuk membuat ukuran EXE menjadi lebih kecil diantaranya :
1. Merubah konfigurasi menjadi Release (Defaultnya Debug).
2. Membuang Informasi RTTI.
3. Mengkompress EXE yang sudah jadi menggunakan software UPX.
Perbandingan ukuran EXE sebelum dan sesudah melewati proses diatas seperti gambar berikut.

Perbandingan ukuran EXE

Langsung saja kita mulai, langkah pertama yaitu merubah konfigurasi menjadi Release.

Klik 2x pada “Release” untuk merubah

Selanjutnya membuang informasi RTTI, yaitu dengan menambahkan kode berikut pada Project Source.

Pilih menu Project-View Source

Yang terakhir mengkompres EXE yang sudah jadi dengan menggunakan UPX.
Sebelumnya download dulu software upxnya jika belum punya pada link berikut https://github.com/upx/upx/releases/download/v3.95/upx-3.95-win32.zip
Yang dibutuhkan hanya upx.exe, copykan upx.exe ke lokasi yang terjangkau path misalnya c:\windows.
Cara menggunakannya cukup mudah seperti gambar berikut.

parameter -9 untuk kompresi maksimum

Kalo diinginkan upx jalan secara otomatis setiap selesai compile bisa juga yaitu dengan mengaturnya pada Build Event.

Project Option – Build events

Langkah-langkah diatas boleh dilakukan salah satu atau semuanya, namun yang perlu diperhatikan bahwa langkah tersebut diatas hanya berlaku untuk platform windows (VCL & Firemonkey).
Demikian sedikit ilmu yang bisa saya bagi pada kesempatan kali ini, semoga bermanfaat.
Wassalamu’alaikum Wr Wb.

Menyiapkan RAD Studio 10.3 Rio untuk develop aplikasi android

Bismillahirrohmanirrohim,
Assalamu’alaikum Wr Wb.

Pada kesempatan kali ini saya akan berbagi tentang langkah-langkah mudah yang diperlukan untuk develop atau membangun aplikasi android menggunakan RAD Studio 10.3 Rio Comunity Edition.

Langkap pertama yang diperlukan dan wajib tentunya harus sudah terinstall RAD Studio 10.3 Rio Comunity Edition, silahkan download pada link berikut jika belum punya.

https://www.embarcadero.com/products/delphi/starter/free-download

Untuk cara download, regitrasi dan instalasi tidak saya bahas disini.
Pada postingan kali ini saya hanya membahas langkah-langkah yang diperlukan sehinggan kita dapat membangun aplikasi android menggunakan RAD Studio 10.3 Rio Comunity Edition.

Untuk menyingkat waktu langsung saja, berikut ini langkah-langkahnya dalam bentuk visual/gambar.

Dari menu “Tools” pilih “Manage Platform”
Pastikan centang “Delphi Android Community”
Centang pada “Java Development .. ” dan “Android SDK …”
Jalankan “SDK Manager”
Download dengan menandai (centang), minimal seperti gambar diatas, yang lain gak usah

Demikian langkah singkat untuk menyiapkan RAD Studio 10.3 Rio agar mendukung develop aplikasi android.

Tutorial modifikasi komponen VCL pada Delphi 10.3 Rio

Assalamu’alaikum Wr Wb.
Bismillahirrohmanirrohim.
Dalam membangun sebuah aplikasi terkadang kita menginginkan sebuah komponen mempunyai fungsi lebih dari yang ada, mungkin kita bisa menggabungkan beberapa komponen atau memainkan koding tertentu agar dapat memenuhi yang kita butuhkan, namun apabila dalam project tersebut terdapat banyak sekali komponen yang dimaksud hal tersebut cukup menyulitkan juga.
Pada kesempatan kali ini saya akan berbagi tutorial cara sederhana untuk menambahkan kemampuan lebih sesuai yang kita butuhkan pada sebuah komponen vcl.
Langsung saja, caranya dapat dilihat pada video berikut.

Contoh source code dapat di download pada Link berikut

Menambahkan tulisan pada progressbar

Bismillahirohmanirrohim,
Assalamu’alaikum Wr Wb.

Terinspirasi dari sebuah pertanyaan pada grup facebook tentang bagaimana cara membuat atau menambahkan tulisan pada progressbar, maka pada kesempatan kali ini saya ingin berbagi ilmu cara menambahkan property Text pada TProgressBar bawaan Delphi sehingga dapat menampilkan progress seperti gambar diatas.

Memang banyak komponen pihak ketiga yang sudah mendukung untuk ini, namun kali ini kita akan melakukannya dengan menggunkan komponen bawaan delphi.

Saya rasa untuk pengantar tidak perlu panjang lebar, kita langsung saja ke source codenya.
Bagi yang males menulis kodenya bisa langsung download contoh aplikasinya pada link dibawah.

 

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ExtCtrls, StdCtrls;

type
  TProgressBar = class(ComCtrls.TProgressBar)
  private
    FText: string;
  protected
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  published
    property Text:string read FText write FText;
  end;
  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    Timer1: TTimer;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
     with ProgressBar1 do
     begin
          Font.Color:=clWhite;
          Font.Style:=[fsBold];
          Text:='Posisi 0%';
          Color:=clNavy;
     end;
end;

{ TProgressBar }

procedure TProgressBar.WMPaint(var Message: TWMPaint);
var
   dc: HDC;
   OldBK: Integer;
   OldFont: HGDIOBJ;
   OldColor: Cardinal;
   rc: TRect;
begin
     rc:=ClientRect; // ambil posisi canvas

     rc.Left:=rc.Left+1;
     rc.Top:=rc.Top+1;
     rc.Right:=rc.Right-1;
     rc.Bottom:=rc.Bottom-1;

     dc:=GetWindowDC(Handle); // ambil handle canvas
     FillRect(dc,rc,Brush.Handle); // kosongkan area canvas

     Inherited; // Tampilkan progress asli

     if FText<>'' then // Jika property Text tidak kosong
     begin
          OldBK:=SetBkMode(dc,TRANSPARENT); // simpan mode background
          OldFont:=SelectObject(dc,Font.Handle); // simpan font
          OldColor:=SetTextColor(dc,Font.Color); // simpan warna
          DrawText(dc,PAnsiChar(FText),Length(FText),rc,DT_SINGLELINE or DT_CENTER or DT_VCENTER); // tulis teks
          SetTextColor(dc,OldColor); // kembalikan warna
          SelectObject(dc,OldFont);  // kembalikan font
          SetBkMode(dc,OldBK); // kembalikan mode background
          ReleaseDC(Handle,dc); // kembalikan handle canvas
     end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
     with ProgressBar1 do
     begin
          Position:=Position+1;
          if Position>=Max then
             Position:=0;
          Text:=Format('Posisi %d%%',[Position]);
     end;
     Application.ProcessMessages;
end;

end.

 

Contoh aplikasi bisa di download di https://app.box.com/s/2esuhbgyraf777fqv7ueyz5nbfnukzv8

 

Semoga tulisan ini bermanfaat bagi saya sendiri dan teman-teman yang membutuhkan.
Aamiin.

Wassalamu’alaikum Wr Wb

Agar komponen TEdit hanya bisa diisi angka dengan acuan nama komponen

Assalamu’alaikum Wa Rohmatullohi Wa Barokatuh.
Taqobalallahu Minna Waminkum Siyamanna Wasiyamakum Taqobal Yaa Kariim.
Minal Aidin wal Faizin, Mohon maaf Lahir dan Bathin.
Selamat Hari Raya Idul Fitri 1436H.

Pada kesempatan kali ini saya ingin berbagi sedikit tips sederhana, yaitu bagaimana kita memperlakukan sebagian atau semua komponen TEdit agar hanya bisa diisi dengan angka dengan acuan nama komponennya, secara otomatis tanpa memberikan pengaturan atau koding satu persatu (yang dilakukan hanya cara penamaan komponen saja).

Untuk membedakan mana komponen TEdit yang hanya bisa diisi dengan angka dan mana yang bisa diisi secara normal, kita buat sebuah aturan yaitu semua komponen TEdit yang namanya dimulai dengan huruf “en” (huruf kecil), maka dia hanya bisa diisi dengan angka, sementara untuk nama yang lain dia akan berfungsi secara normal.

Langsung saja, caranya cukup sederhana yaitu dengan meng-override procedure KeyPress milik TEdit …

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  // Tambahkan ini
  TEdit = class(StdCtrls.TEdit)
    procedure KeyPress(var Key: Char); override;
  end;
  // Sampai sini
  TForm1 = class(TForm)
    enEdit1: TEdit;
    Edit2: TEdit;
    enEdit3: TEdit;
    Edit4: TEdit;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


{ TEdit }

procedure TEdit.KeyPress(var Key: Char);
begin
     inherited;
     if (Pos('en',Name)=1) and  // Jika nama diawali dengan "en"
        (Pos(Key,'0123456789-'#8#13+DecimalSeparator)=0) then
        Key:=#0; // hanya menerima angka dan pemisah desimal
end;


end.

Semoga bermanfaat.
Contoh source code dapat didownload di https://app.box.com/s/enc1s0d4jntrozig5dike4uz31g245qy

Komunikasi Delphi-Excel menggunakan VBA


Bismillahirrohmanirrohim,
Assalamu’alaikum Wr Wb.
Sekitar 2 tahun (2012) yang lalu saya pernah menulis artikel “Export DBGrid ke Microsoft Excel” di grup facebook
(https://www.facebook.com/notes/komunitas-programmer-delphi-dan-interbase-indonesia/export-dbgrid-ke-microsoft-excel/390918654286205).
Alhamdulillah ternyata banyak yang tertarik dengan artikel tersebut,
unit tersebut telah didownload 457 kali pada saat postingan ini ditulis.

Kali ini saya tidak membahas tentang mengexport DBGrid/database ke Microsoft Excel namun hanya melakukan perbaikan/update pada unit yang ada dengan ditambahkan dokumentasi singkat dan contoh program.
Unit yang saya upload ada 2 versi yaitu untuk Delphi 7 dan Delphi 2006 (karena saya cuman punya 2 versi delphi itu .. hehehe)

Update Desember 2018 – Tambahan dukungan untuk Delphi 10.1-Berlin, Delphi 10.2-Tokyo 32/64bit dan Delphi 10.3-Rio 32/64bit.

Untuk menggunakan unit ini cukup mudah, copy unit yang sesuai dengan versi delphi yang anda pakai, taruh di folder lib atau jadikan satu dengan aplikasi.
Selanjutnya tambahkan VsrExcelOle pada klausa uses.

Berikut ini contoh potongan kodenya …

uses ..... VsrExcelOle;

var
  Form1: TForm1;
  ex: VsrExcel;

implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
     if not Assigned(ex) then
     begin
          ex:=VsrExcel.Create; // komunikasi dengan excel
          ex.Show; // tampilkan excel
     end;
     ex.New; // buat workbook baru
     ex.AutoSelect:=True; // supaya otomatis aktifkan cell setelah menulis
     ex.Write('A1',Edit1.Text); // tulis Edit1 pada Cell A1
     if CheckBox1.Checked then
        ex.Font.Bold:=True; // Tebalkan jika dicentang
     ex.Write('A2',Edit2.Text); // tulis Edit1 pada Cell A2
     if CheckBox2.Checked then
        ex.Font.Bold:=True; // Tebalkan jika dicentang
end;

Pada object VsrExcel ada property App yang dapat kita gunakan untuk memasukkan perintah VBA lainnya yang belum tersedia di unit ini.

Unit beserta dokumentasi dan contoh programnya dapat
didownload di https://app.box.com/s/f9c4ebde3a0ce86a1895
Bila ingin memperdalam VBA Excel silahkan baca di helpnya Excel, kalo gak punya bisa juga
didownload di https://app.box.com/s/1i5ivb6k04jgz0822ez1

Semoga bermanfaat

Cara mudah dan cepat mencari port serial sebuah alat / device

Assalamu’alaikum Wr Wb,

Dalam membuat aplikasi yang berhubungan dengan pelalatan luar seperti microcontroller, sms gateway, dan lain-lain tentunya kita akan berhubungan dengan port serial, memang tidak semua peralatan luar menggunakan port serial (COM), namun kali ini kita batasi pembahasan hanya pada port serial karena ini yang paling sering digunakan.

Saat kita menggunakan peralatan (device) khususnya yang menggunakan colokan usb sering kalikita mengalami sedikit kendala karena portnya berubah-ubah setiap kali ditancapkan pada colokan yang berbeda.

Beruntunglah windows menyediakan informasi terkait peralatan serial yang digunakan pada registry sehingga kita tidak perlu melakukan scanning setiap port yang ada untuk mengetahui device (alat) kita pada COM berapa.

Informasi tersebut bisa kita baca dari HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM

pada kasus ini saya mencoba mendeteksi port dari USB to TTL yang saya gunakan untuk komunikasi dengan microcontroller.

 

Tampilan registry sebelum alat dicolokkan

 

Tampilan registry setelah alat dicolokkan

dari tampilan diatas tampak bahwa alat yang saya gunakan teridentifikasi sebagai “\Device\ProlificSerial2” kita ambil “Prolific” sebagai kata kuncinya karena kata “Serial2” bisa berubah, sebagaimana yang tampak pada Devive Manager.

OK, langsung saja berikut ini saya tunjukkan bagaimana cara membaca informasi tersebut menggunakan delphi yang nantinya akan kita masukkan ke komponen Comport.

procedure TForm1.FormCreate(Sender: TObject);
var
   key: HKEY;
   index: Integer;
   VarName,value: string;
   sz: Cardinal;
   dw: DWORD;
begin
     RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        'HARDWARE\DEVICEMAP\SERIALCOMM',
        0,KEY_QUERY_VALUE,key);
     index:=0;
     repeat
           sz:=256;
           SetLength(VarName,sz);
           dw:=256;
           SetLength(value,dw);
           if 

RegEnumValue(key,index,PChar(VarName),sz,nil,nil,PByte(value),@dw)<>ERROR_SUCCESS then
              Break;
           Inc(index);
           SetLength(VarName,sz);
           SetLength(value,dw);
           Memo1.Lines.Add(VarName+' » '+value);
           if pos('\Device\Prolific',VarName)=1 then
           begin
                ComPort1.Port:=value;
                Break;
           end;
     until False;
     RegCloseKey(key);
     ComPort1.Open;
end;

Semoga bermanfaat.

VsrDotMatrix – Unit sederhana untuk printer dot matrik

unit VsrDotMatrixs;
{
 Imam Chalimi
 Agustus, 2006

 Rev:
 03/09/2006 : First complete properties.
 05/09/2006 : SetMargin Added
}

interface

uses
    Windows,
    SysUtils,
    Classes;

const
     VDMA_LEFT     = 0;
     VDMA_RIGHT    = 1;
     VDMA_CENTER   = 2;
     VDMA_JUSTIFY  = 3;

     PRN_INIT        = #27'@';
     PRN_FF          = #12;
     PRN_LF          = #10;
     PRN_PAGE_LENGTH = #27'C';
     PRN_CF_BOTTOM   = #27'N';
     PRN_LEFT        = #27'l';
     PRN_RIGHT       = #27'Q';
     PRN_FONT_ROMAN  = #27'k'#0;
     PRN_FONT_SANS   = #27'k'#1;
     PRN_FONT_COUR   = #27'k'#2;
     PRN_10CPI       = #27'P';
     PRN_12CPI       = #27'M';
     PRN_15CPI       = #27'g';
     PRN_DRAFT       = #27'x'#0;
     PRN_NLQ         = #27'x'#1;
     PRN_ITALIC_ON   = #27'4';
     PRN_ITALIC_OFF  = #27'5';
     PRN_BOLD_ON     = #27'E';
     PRN_BOLD_OFF    = #27'F';
     PRN_ULINE_ON    = #27'-'#1;
     PRN_ULINE_OFF   = #27'-'#0;
     PRN_COND_ON     = #15;
     PRN_COND_OFF    = #18;
     PRN_DBL_WIDTH   = #27'W';
     PRN_DBL_WIDTH_ON    = #27'W'#1;
     PRN_DBL_WIDTH_OFF   = #27'W'#0;
     PRN_DBL_HEIGTH  = #27'w';
     PRN_DBL_HEIGTH_ON   = #27'w'#1;
     PRN_DBL_HEIGTH_OFF  = #27'w'#0;
     PRN_SPC_180     = #27'3';

type
    TVsrDotMatrix = class
      private
        FAbout,
        FTarget: string;
        FFile: TextFile;
        FNLQ,
        FBold,
        FItalic,
        FUnderline,
        FDWidth: Boolean;
        FFontSize,
        FMarginLeft,
        FMarginRight,
        FMarginTop,
        FMarginBottom,
        FLine,
        FPageLength: Integer;
        FSpacing: Real;
        FAlign: Integer;
        procedure SetNLQ(value:Boolean);
        procedure SetBold(value:Boolean);
        procedure SetItalic(value:Boolean);
        procedure SetUnderline(value:Boolean);
        procedure SetDWidth(value:Boolean);
        procedure SetAlign(value:Integer);
        procedure SetFont(value:Integer);
        procedure SetSpacing(value:Real);
        procedure SetLeftMargin(value:Integer);
        procedure SetRightMargin(value:Integer);
        procedure SetTopMargin(value:Integer);
        procedure SetBottomMargin(value:Integer);
      public
        constructor Create;
        function Open:Boolean;
        procedure Close;
        procedure InitPrinter;
        procedure FormFeed;
        procedure NextPage;
        procedure Print(Text:string='';NewLine:Boolean=True);
        function Repl(iLength:Integer;s:string=' '):string;
        function AddSpace(Text:string;iLength:Integer;
                 iAlign:Integer=VDMA_LEFT):String;
        function SplitWord(Text:string;iWidth:Integer;
                 iAlign:Integer=VDMA_LEFT):string;
      published
        property About:string read FAbout;
        property Target:string read FTarget write FTarget;
        property NLQ:Boolean read FNLQ write SetNLQ;
        property Bold:Boolean read FBold write SetBold;
        property Italic:Boolean read FItalic write SetItalic;
        property Underline:Boolean read FUnderline write SetUnderline;
        property DoubleWidth:Boolean read FDWidth write SetDWidth;
        property FontSize:Integer read FFontSize write SetFont;
        property Align:Integer read FAlign write SetAlign;
        property Spacing:Real read FSpacing write SetSpacing;
        property MarginLeft:Integer read FMarginLeft write SetLeftMargin;
        property MarginRight:Integer read FMarginRight write SetRightMargin;
        property MarginTop:Integer read FMarginTop write SetTopMargin;
        property MarginBottom:Integer read FMarginBottom write SetBottomMargin;
        property PageLength:Integer read FPageLength write FPageLength;
    end;

implementation

{ TVsrDotMatrix }

function TVsrDotMatrix.AddSpace(Text: string; iLength,
  iAlign: Integer): String;
begin
     Result:=Text;
     case iAlign of
          VDMA_LEFT: while Length(Result)<iLength do
                     Result:=Result+' ';
          VDMA_RIGHT: while Length(Result)<iLength do
                      Result:=' '+Result;
          VDMA_CENTER: begin
                            while Length(Result)<iLength do
                                  Result:=' '+Result+' ';
                            if Length(Result)>iLength then
                               SetLength(Result,iLength);
                       end;
     end;
end;

procedure TVsrDotMatrix.Close;
begin
     CloseFile(FFile);
end;

constructor TVsrDotMatrix.Create;
begin
     FAbout:='VsrDotMatrix by Imam Chalimi #20060905.0600';
     FTarget:='prn';
end;

procedure TVsrDotMatrix.FormFeed;
begin
     Print(PRN_FF,False);
     FLine:=0;
end;

procedure TVsrDotMatrix.InitPrinter;
begin
     Print(PRN_INIT+PRN_DRAFT+PRN_COND_OFF,False);
     MarginLeft:=0;
     MarginTop:=0;
end;

procedure TVsrDotMatrix.NextPage;
begin
     if FPageLength=0 then
        FormFeed
     else
         while FLine<FPageLength do
               Print;
     FLine:=0;
end;

function TVsrDotMatrix.Open: Boolean;
begin
     if FTarget='' then
        FTarget:='prn';
     AssignFile(FFile,FTarget);
     {$I-}
     Rewrite(FFile);
     {$I+}
     Result:=(IOResult=0);
     FLine:=0;
     FPageLength:=0;
end;

procedure TVsrDotMatrix.Print(Text: string; NewLine: Boolean);
begin
     if (FAlign=VDMA_RIGHT) and (FMarginRight>0) then
        while Length(Text)<FMarginRight do
              Text:=' '+Text;
     if (FAlign=VDMA_CENTER) and (FMarginRight>0) then
        while Length(Text)<FMarginRight do
              Text:=' '+Text+' ';
     if NewLine then
     begin
          Writeln(FFile,Text);
          Inc(FLine);
     end
     else
        Write(FFile,Text);
end;

procedure TVsrDotMatrix.SetAlign(value: Integer);
begin
     FAlign:=value;
end;

procedure TVsrDotMatrix.SetBold(value: Boolean);
begin
     FBold:=value;
     if value then
        Print(PRN_BOLD_ON,False)
     else
        Print(PRN_BOLD_OFF,False);
end;

procedure TVsrDotMatrix.SetDWidth(value: Boolean);
begin
     FDWidth:=value;
     if value then
        Print(PRN_DBL_WIDTH+#1,False)
     else
         Print(PRN_DBL_WIDTH+#0,False);
end;

procedure TVsrDotMatrix.SetFont(value: Integer);
begin
     case value of
          10: if FFontSize=20 then
                 Print(PRN_COND_OFF,False)
              else
                  Print(PRN_10CPI,False);
          12: Print(PRN_12CPI,False);
          15: Print(PRN_15CPI,False);
          20: Print(PRN_COND_ON,False);
     else
         Print(PRN_COND_OFF,False);
     end;
     FFontSize:=value;
end;

procedure TVsrDotMatrix.SetItalic(value: Boolean);
begin
     FItalic:=value;
     if value then
        Print(PRN_ITALIC_ON,False)
     else
         Print(PRN_ITALIC_OFF,False);
end;

procedure TVsrDotMatrix.SetNLQ(value: Boolean);
begin
     FNLQ:=value;
     if value then
        Print(PRN_NLQ,False)
     else
         Print(PRN_DRAFT,False);
end;

procedure TVsrDotMatrix.SetSpacing(value: Real);
begin
     FSpacing:=value;
     Print(PRN_SPC_180+chr(trunc(30*FSpacing)));
end;

procedure TVsrDotMatrix.SetUnderline(value: Boolean);
begin
     FUnderline:=value;
     if value then
        Print(PRN_ULINE_ON,False)
     else
        Print(PRN_ULINE_OFF,False);
end;

function TVsrDotMatrix.Repl(iLength: Integer;s:string): string;
var
   i: Integer;
begin
     Result:='';
     for i:=1 to iLength do
         Result:=Result+s;
end;

function TVsrDotMatrix.SplitWord(Text: string; iWidth,
  iAlign: Integer): string;
var
   aOld,aNew: array of string;
   i,n: Integer;
begin
     while pos(#10,Text)>0 do
           Text[pos(#10,Text)]:=' ';
     while pos(#13,Text)>0 do
           Text[pos(#13,Text)]:=' ';
     while pos('  ',Text)>0 do
           Delete(Text,pos('  ',Text),1);
     Text:=Trim(Text);
     i:=0;
     while pos(' ',Text)>0 do
     begin
          Inc(i);
          SetLength(aOld,i);
          aOld[i-1]:=copy(Text,1,pos(' ',Text)-1);
          Delete(Text,1,pos(' ',Text));
     end;
     Inc(i);
     SetLength(aOld,i);
     aOld[i-1]:=Text;
     n:=0;
     for i:=1 to Length(aOld) do
     begin
          if (n=0) or (Length(aNew[n-1])+Length(aOld[i-1])>iWidth) then
          begin
               Inc(n);
               SetLength(aNew,n);
          end;
          aNew[n-1]:=aNew[n-1]+aOld[i-1]+' ';
     end;
     Result:='';
     for i:=1 to Length(aNew) do
         Result:=Result+aNew[i-1]+#13#10;
end;

procedure TVsrDotMatrix.SetBottomMargin(value: Integer);
begin
     FMarginBottom:=value;
end;

procedure TVsrDotMatrix.SetLeftMargin(value: Integer);
begin
     FMarginLeft:=value;
     Print(PRN_LEFT+chr(value),False);
end;

procedure TVsrDotMatrix.SetRightMargin(value: Integer);
begin
     FMarginRight:=value;
     Print(PRN_RIGHT+chr(value),False);
end;

procedure TVsrDotMatrix.SetTopMargin(value: Integer);
begin
     FMarginTop:=value;
end;

end.

Cara mudah mengambil waktu saat ini dari Internet menggunakan Indy 10


Terinspirasi dari pertanyaan seorang member pada sebuah grup.
Diawali dengan pertanyaan .. bagaimana agar datetimepicker pada aplikasi mengikuti jam yang ada di komputer ?
Kemudian dilanjutkan .. bagaimana kalo jamnya mengambil dari server ?
Berlanjut lagi .. kalo mengambil dari internet bagaimana ?

Kali ini kita hanya akan membahas yang terakhir yaitu mengambil waktu saat ini dengan bantuan komponen TidSNTP (Indy 10) menggunakan Delphi.

Caranya mudah sekali, kita tinggal manfaatkan komponen siap pake yaitu TidSNTP punya Indy 10.

Langsung saja ya … ini source codenya ..

unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient,
  IdSNTP, ExtCtrls;

type
  TFMain = class(TForm)
    Label1: TLabel;
    IdSNTP1: TIdSNTP;
    Label2: TLabel;
    Label3: TLabel;
    stJamPC: TStaticText;
    stJamInet: TStaticText;
    bCocok: TButton;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure bCocokClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
     tmServer = 'pool.ntp.org'; // internet time server
     (*
       Alternatif lain :
       time.windows.com
       time.nist.gov
     *)

var
  FMain: TFMain;
  Delta: TDateTime; // untuk menyimpan selisih waktu PC vs Internet

implementation

{$R *.dfm}

procedure TFMain.bCocokClick(Sender: TObject);
begin
     IdSNTP1.SyncTime;
     Delta:=0;
end;

procedure TFMain.FormCreate(Sender: TObject);
begin
     with IdSNTP1 do
     begin
          Host:=tmServer;
          Delta:=Now-DateTime; // menghitung selisih waktu
     end;
end;

procedure TFMain.Timer1Timer(Sender: TObject);
begin
     stJamPC.Caption:=FormatDateTime('dd mmmm yyyy - hh:nn.ss',Now);
     stJamInet.Caption:=FormatDateTime('dd mmmm yyyy - hh:nn.ss',Now-Delta);
end;

end.

Cara kerjanya sebagai berikut :

Pada event CreateForm kita akan mengambil selisih waktu yang ada di komputer dibandingkan dengan waktu yang ada di internet dan disimpan dalam variable Delta.

Variable Delta ini nantinya kita manfaatkan untuk menampilkan secara terus menerus setiap detik dengan menggunakan komponen TTimer.

Kenapa harus disimpan dulu selisihnya? kok gak langsung ambil aja dari internet secara realtime?

Tujuannya adalah untuk menghemat bandwidth sehingga program tidak menjadi berat karena selalu mengakses ke internet apalagi kalo lagi lemot, toh setelah selisih kita ketahui maka kita akan bisa menghitung waktu yang ada di internet dengan menggunakan selisih tadi.

Sekian dulu ya …
Contoh project beserta source codenya dapat didownload di https://www.box.com/s/msiye9u8xryp2pr2b8kp

Semoga bermanfaat.

Membuat form dengan bentuk mengikuti gambar

Umumnya sebuah form yang kita buat menggunakan delphi bentuknya adalah kotak, namun sebenarnya kita bisa membuat form dengan bentuk yang tidak biasa seperti lingkaran, segitiga, poligon atau bahkan bentuk sesuai yang kita inginkan, misalnya mengikuti bentuk gambar.

Untuk membuat (baca:memotong) form menjadi tidak kotak kita menggunakan fungsi dari Windows API yaitu SetWindowRgn.

Pada SetWindowRgn telah disediakan bentuk-bentuk umum seperti kotak, lingkaran atau segi banyak.

Lantas .. bagaimana cara membuat form dengan bentuk yang tidak umum seperti gambar diatas?

Untuk membuat region dengan bentuk tidak biasa perlu dibuat (baca: copas dari internet) unit (fungsi) sehingga lebih mudah dan tidak perlu pusing.

Langsung saja ..

Pertama-tama siapkan dua buah gambar seperti berikut yang nantinya akan diload ke TImage (imgNormal & imgMask).

Gambar pertama diload ke imgNormal

Gambar kedua diload ke imgMask

Ukuran dari kedua gambar harus sama persis.

… yang perlu diperhatikan dalam membuatnya adalah ..

  • Set property BorderStyle pada form menjadi bsNone.
  • Siapkan 2 buat TImage (imgNormal & imgMask), imgNormal untuk menyimpan gambar yg tampil dan imgMask untuk menyimpan gambar pemotong.
  • Set Property Left & Top imgNormal menjadi 0 sehingga akan berada di kiri atas form.
  • Set Propeety AutoSize imgNormal menjadi True.
  • Set property visible pada imgMask menjadi False.

Berikut ini contoh potongan kode yang akan kita tulis di event OnCreate

procedure TFMain.FormCreate(Sender: TObject);
var
   hr,br: HRGN;
   bmp: TBitmap;
begin
     bmp:=TBitmap.Create;
     bmp.Assign(ImgMask.Picture.Graphic);
     hr:=BitmapToRegion(bmp.Handle);
     bmp.Free;
     br:=CreateRectRgnIndirect(mInfo.BoundsRect);
     CombineRgn(hr,hr,br,RGN_OR);
     br:=CreateRectRgnIndirect(btClose.BoundsRect);
     CombineRgn(hr,hr,br,RGN_OR);
     SetWindowRgn(Handle,hr,True);
end;

Karena form ini tidak mempunyai Caption, lantas bagaimana caranya jika kita ingin menggesernya?
Agar form bisa kita geser dengan Click-Drag pada selain Caption, maka kita harus melakukan intercept pada Message WM_NCHITTEST seperti kode berikut ini

  private
    { Private declarations }
    procedure GeserForm(var msg: TWMNCHitTest);
              message WM_NCHITTEST;

Bagi yang tertarik untuk membuat aplikasi dengan form seperti gambar diatas silahkan download contoh project beserta source codenya di ..
https://www.box.com/s/n29a3n5x10srvrr1jvqg

Semoga bermanfaat
Wassalam

Imam Chalimi Muslim