#! perl -w ####################################################################### # NotePad.pl : Notepad clone with Perl & Win32::GUI. ####################################################################### use strict; use warnings; use Win32::GUI qw( MB_ICONQUESTION MB_ICONINFORMATION MB_YESNOCANCEL MB_OK IDYES IDCANCEL ); my $CurrentFile = ""; my $FindDlg; my $EditFont = new Win32::GUI::Font ( -name => "Fixedsys", -size => 12, ); # Make Menu my $Menu = Win32::GUI::MakeMenu( "&File" => "File", " > &New" => { -name => "Exit", -onClick => \&Notepad_OnNewFile }, " > &Open..." => { -name => "Open", -onClick => \&Notepad_OnOpenFile }, " > &Save" => { -name => "Save", -onClick => \&Notepad_OnSaveFile }, " > Save &As ..." => { -name => "SaveAs", -onClick => \&Notepad_OnSaveAsFile }, " > -" => 0, " > Print &Setup ..." => { -name => "PrintSetup", -enabled => 0 }, " > &Print" => { -name => "Print", -enabled => 0 }, " > -" => 0, " > E&xit" => { -name => "Exit", -onClick => \&Notepad_OnQuitFile }, "&Edit" => "Edit", " > &Undo" => { -name => "Undo", -onClick => sub { my $self = shift; $self->Edit->Undo(); 0; } }, " > -" => 0, " > Cu&t" => { -name => "Cut", -onClick => sub { my $self = shift; $self->Edit->Cut(); 0; } }, " > &Copy" => { -name => "Copy", -onClick => sub { my $self = shift; $self->Edit->Copy(); 0; } }, " > &Paste" => { -name => "Paste", -onClick => sub { my $self = shift; $self->Edit->Paste(); 0; } }, " > &Delete" => { -name => "Delete", -onClick => sub { my $self = shift; $self->Edit->Clear(); 0; } }, " > -" => 0, " > &Select All" => { -name => "SelectAll", -onClick => sub { my $self = shift; $self->Edit->SelectAll(); 0; } }, " > -" => 0, " > Choose &Font..." => { -name => "ChooseFont", -onClick => \&Notepad_OnChooseFont }, "F&ind" => "_Find", " > &Find..." => { -name => "Find", -onClick => \&Notepad_OnFind }, " > Find &Next" => { -name => "FindNext", -onClick => \&Notepad_FindText }, "&?" => "?", " > &Help" => { -name => "Help", -enabled => 0 }, " > -" => 0, " > &About" => { -name => "About", -onClick => \&Notepad_OnAbout }, ); # Create Main Window my $Window = new Win32::GUI::Window ( -name => "Window", -title => "Notepad", -pos => [100, 100], -size => [400, 400], -menu => $Menu, -onResize => \&Notepad_OnSize, -onInitMenu => \&Notepad_OnInitMenu, -onTerminate => \&Notepad_OnQuitFile, ) or die "new Window"; # Create Textfield for Edit Text $Window->AddTextfield( -name => "Edit", -pos => [0, 0], -size => [100, 100], -multiline => 1, -hscroll => 1, -vscroll => 1, -autohscroll => 1, -autovscroll => 1, -keepselection => 1 , -font => $EditFont, ); # Create Find DialogBox $FindDlg = new Win32::GUI::DialogBox( -name => "FindDlg", -title => "Find", -pos => [ 150, 150 ], -size => [ 360, 115 ], -parent => $Window, # Set $Window as parent for be modeless but not Top. ); # Text to find $FindDlg->AddTextfield ( -name => "FindDlg_Text", -pos => [10, 12], -size => [220, 21], -prompt => [ "Find : ", 30], -tabstop => 1, -onChange => sub { $FindDlg->FindDlg_Find->Enable(length($FindDlg->FindDlg_Text->Text) != 0); 0; }, ); # Case sensitive checkbox $FindDlg->AddCheckbox ( -name => "FindDlg_Case", -text => "Match case", -pos => [10, 60], -size => [100, 21], -tabstop => 1, ); # $FindDlg->AddGroupbox( -text => "Direction", -pos => [140, 40], -size => [120, 40], ); # Search Up RadioButton $FindDlg->AddRadioButton( -name => "FindDlg_FindUp", -text => "Up", -pos => [150, 55], -size => [50, 20], -group => 1, ); # Search Down RadioButton $FindDlg->AddRadioButton( -name => "FindDlg_FindDown", -text => "Down", -pos => [200, 55], -size => [50, 20], -tabstop => 1, -checked => 1, ); # Find button $FindDlg->AddButton ( -name => "FindDlg_Find", -text => "&Find", -pos => [270, 10], -size => [75 , 21], -onClick => sub { Notepad_FindText($Window); 0; }, -group => 1, -tabstop => 1, ); # Cancel Button $FindDlg->AddButton ( -name => "FindDlg_Cancel", -text => "C&ancel", -pos => [270, 40], -size => [75 , 21], -onClick => sub { $FindDlg->Hide(); 0; }, -tabstop => 1, ); # Set Focus to Edit and show Window $Window->Edit->SetFocus(); $Window->Show(); Win32::GUI::Dialog(); ####################################################################### # Window Event # Resize Window sub Notepad_OnSize { my ($self) = @_; my ($width, $height) = ($self->GetClientRect())[2..3]; $self->Edit->Resize($width+1, $height+1) if exists $self->{Edit}; } # Refresh menu item sub Notepad_OnInitMenu { my $self = shift; # File Menu # Edit Menu my $bSel = $self->Edit->HaveSel(); $Menu->{Undo}->Enabled($self->Edit->CanUndo()); $Menu->{Cut}->Enabled($bSel); $Menu->{Copy}->Enabled($bSel); $Menu->{Paste}->Enabled($self->Edit->CanPaste()); $Menu->{Delete}->Enabled($bSel); # Find Menu $Menu->{FindNext}->Enabled(length($FindDlg->FindDlg_Text->Text) != 0); 0; } # ####################################################################### sub NotePad_CheckSaveCurrentFile { my $self = shift; # Check if need to save if ($self->Edit->Modify()) { my $ret = $self->MessageBox ( "Save current file ?", "Notepad", MB_ICONQUESTION | MB_YESNOCANCEL); if ($ret == IDYES) { Notepad_OnSaveFile($self); } elsif ($ret == IDCANCEL) { return IDCANCEL; } } return IDYES; } # Find Text in Edit (search is defined by FindDlg) sub Notepad_FindText { my $self = shift; my $text = $self->Edit->Text; # Get Edit text my $find = $FindDlg->FindDlg_Text->Text; # Get text to find my ($start, $end) = $self->Edit->GetSel(); # Get current Edit Selection my $index; unless ( $FindDlg->FindDlg_Case->Checked() ) { # Check for case unsensitive search $text = lc $text; # Transform both to lowercase $find = lc $find; } if ($FindDlg->FindDlg_FindDown->Checked()) { # Search to botton ? $index = index($text, $find, $end); } else { # Or Search to Up ? $index = rindex($text, $find, $start-1); } if ($index >= 0) { $self->Edit->SetSel($index, $index + length $find); # Select text found $self->Edit->ScrollCaret(); # Make selected text visible } else { Win32::GUI::MessageBeep; # Sound if not found } 0; } ####################################################################### # Menu Event # # File menu # # New File sub Notepad_OnNewFile { my $self = shift; # Need to save current file ? return 0 if NotePad_CheckSaveCurrentFile($self) == IDCANCEL; # Set Default filename $CurrentFile = ""; $self->Text("Notepad"); # Change main window Title # Reset Edit $self->Edit->Text(""); # Set Edit text Empty $self->Edit->EmptyUndoBuffer(); # Empty Undo buffer $self->Edit->Modify(0); # Set Modified state to false $self->Edit->SetFocus(); # Focus to Edit 0; } # Open file sub Notepad_OnOpenFile { my $self = shift; # Need to save current file ? return 0 if NotePad_CheckSaveCurrentFile($self) == IDCANCEL; # Open a file my $file = Win32::GUI::GetOpenFileName( -owner => $Window, -title => "Open a text file", -filter => [ 'Perl script (*.pl)' => '*.pl', 'Text file (*.txt)' => '*.txt', 'All files' => '*.*', ], ); # Load file if ($file) { # Keep Current file. $CurrentFile = $file; $self->Text( "$CurrentFile - Notepad"); # Load File in Edit $self->Edit->LockWindowUpdate; # Lock Painting on Edit $self->Edit->Text(""); # Empty Edit open F, "<$file" or die "Open file : $file"; while ( ) { chomp; $self->Edit->Append($_."\r\n"); # Need to add \r } close F; # Reset Edit $self->Edit->EmptyUndoBuffer(); $self->Edit->Modify(0); $self->Edit->Select(0,0); # Set Cursor on first char $self->Edit->ScrollCaret(); # Make cursor visible $self->Edit->LockWindowUpdate(1); # Unlock Painting on Edit $self->Edit->SetFocus(); } elsif (Win32::GUI::CommDlgExtendedError()) { $self->MessageBox ("ERROR : ".Win32::GUI::CommDlgExtendedError(), "GetOpenFileName Error"); } 0; } # Save File sub Notepad_OnSaveFile { my $self = shift; # No filename, call SaveAs. return Notepad_OnSaveAsFile($self) unless (-f $CurrentFile ); # Retrieve Text my $text = $self->Edit->Text; $text =~ s/\r\n/\n/mg; # Need to remove \r # Save file open F, ">$CurrentFile" or die "Open file : $CurrentFile"; print F $text; close F; # Reset Edit state $self->Edit->Modify(0); $self->Edit->SetFocus(); 0; } # Save File sub Notepad_OnSaveAsFile { my $self = shift; # Open a file my $file = Win32::GUI::GetSaveFileName( -owner => $Window, -title => "Save As", -file => $CurrentFile, -filter => [ 'Perl script (*.pl)' => '*.pl', 'Text file (*.txt)' => '*.txt', 'All files' => '*.*', ], -defaultextension => "pl", -createprompt => 1, ); # Save file if (defined $file) { # Keep Current file. $CurrentFile = $file; $self->Text( "$CurrentFile - Notepad"); # Retrieve Text my $text = $self->Edit->Text(); $text =~ s/\r\n/\n/mg; # Save file open F, ">$file" or die "Open file : $file"; print F $text; close F; # Reset Edit state $self->Edit->Modify(0); $self->Edit->SetFocus(); } elsif (Win32::GUI::CommDlgExtendedError()) { $self->MessageBox ("ERROR : ".Win32::GUI::CommDlgExtendedError(), "GetSaveFileName Error"); } 0; } # Quit Notepad sub Notepad_OnQuitFile { my $self = shift; # Need to save current file ? if (NotePad_CheckSaveCurrentFile($self) == IDCANCEL) { return 0; } else { return -1; } } # # Edit menu # sub Notepad_OnChooseFont { my $self = shift; # Choose font my @font = Win32::GUI::ChooseFont( -owner => $Window, $EditFont->Info() ); if ($#font) { $EditFont = new Win32::GUI::Font (@font); $self->Edit->Change( -font => $EditFont); $self->Edit->Update(); } 0; } # # Find menu # sub Notepad_OnFind { # Set focus and Enable Find button as appropriate $FindDlg->FindDlg_Text->SetFocus; $FindDlg->FindDlg_Find->Enable(length($FindDlg->FindDlg_Text->Text) != 0); $FindDlg->Show(); 0; } # # Help menu # # About box sub Notepad_OnAbout { my $self = shift; $self->MessageBox( "Perl Notepad, version 1.0\r\n". "Win32::GUI Demo", "About...", MB_ICONINFORMATION | MB_OK, ); 0; } # #######################################################################