1
MỤC LỤC
1. Giới thiệu đề tài 2
1.1. Yêu cầu chức năng 2
1.2. Giải pháp công nghệ 2
1.2.1. Ngôn ngữ C Sharp 2
1.2.2. Giới thiệu về Windows Presentation Foundation (WPF) 3
1.2.3. Giải pháp kỹ thuật 4
2. Xây dựng giao diện với XAML 4
2.1. Layout 4
2.2. Menu 6
2.3. Document Viewer 6
2.4. Các button điều khiển 7
3. Các phương thức và sự kiện 9
3.1. OpenFile Dialog 9
3.2. Chuyển đổi file PowerPoint sang XPS 9
3.3. Mở file XPS với DocumentViewer 9
3.4. Xóa file tạm 11
3.5. Các phương thức điều khiển button 13
3.6. Cập nhật trạng thái hiển thị trang 15
4. Tài liệu tham khảo 17
2
1. Giới thiệu đề tài
1.1. Yêu cầu chức năng
Mục tiêu của đề tài là viết một ứng dụng có khả năng mở được file Microsoft PowerPoint
sử dụng ngôn ngữ lập trình Csharp. Từ yêu cầu trên có thể rút ra một số yêu cầu chức
năng của ứng dụng như sau:
Có khả năng trình chiếu một file PowerPoint.
Sử dụng các button như Next, Back… trên giao diện phần mềm và các phím trên
bàn phím để điều khiển quá trình trình chiếu.
Hiển thị trạng thái của tài liệu đang mở như số trang…
Nhảy tới một trang bất kỳ thông qua việc nhập số của trang cần mở (Go to page).
Giao diện đơn giản, dễ sử dụng.
Quá trình làm việc nhanh, ít lỗi, chiếm ít tài nguyên phần cứng.
1.2. Giải pháp công nghệ
1.2.1. Ngôn ngữ C Sharp
C# là ngôn ngữ lập trình nằm trong bộ .NET của Microsoft.
Được phát triển từ C và C++ nhưng được thêm vào những đặc tính mới giúp ngôn ngữ
này dễ sử dụng hơn. C# loại bỏ một số sự phức tạp của C++ như macro, template, đa kế
thừa hoặc dễ nhận thấy hơn là việc thay thế các toán tử (*), (), (.) của C++ thành một
toán tử duy nhất (.). Việc này hạn chế sự nhầm lẫn cho lập trình viên, cũng dễ dàng hơn
của những người mới bắt đầu.
3
C# là ngôn ngữ hướng đối tượng, mạnh mẽ nhưng cũng rất mềm dẻo. Với C# lập trình
viên có thể tạo hầu hết các ứng dụng bao gồm xử lý văn bản, đồ họa, …có chăng sự giới
hạn chính là sức sáng tạo của mỗi lập trình viên.
1.2.2. Giới thiệu về Windows Presentation Foundation (WPF)
Để tạo giao diện cho một ứng dụng CSharp Microsoft có cung cấp 2 công cụ đó là
Windows Form (WF) và Windows Presentation Foundation (WPF) trong đó Windows
Form là một công nghệ cho phép tạo giao diện người dùng rất phổ biến hiện nay và được
rất nhiều trường học đưa vào chương trình giảng dạy. Tuy nhiên WF còn tồn tại khá
nhiều nhược điểm như để tạo một ứng dụng có những tính năng riêng biệt như ảnh 2
chiều, 3 chiều, đa phương tiện… lập trình viên phải thông thuộc rất nhiều kỹ thuật như
GDI+, DirectX,…Vì vậy khi cho ra đời Framwork .NET 3.0 Microsoft đã giới thiệu một
giải pháp mới là WPF.
Việc tạo giao diện trên WPF được thực hiện thông qua các file .xaml. Đó là các file có
cấu trúc tương tự như các thẻ web html. Lập trình viên có thể sử dụng các thao tác kéo
thả như WF, tuy nhiên việc lập trình giao diện bằng các câu lệnh thậm chí còn nhanh và
chính xác hơn bởi cơ chế hiển thị giao diện song song với code giúp họ có thể có cái nhìn
trực quan cho giao diện ngay từ những dòng code đầu tiên.
WPF đáp ứng hầu hết các yêu cầu cho việc phát triển ứng dụng bao gồm đồ họa 2D, 3D,
đa phương tiện…Ở mức đơn giản hơn và thiết thực với đề tài này là khả năng xử lý văn
bản. WPF hỗ trợ 3 dạng văn bản đó là : văn bản cố định, văn bản thích nghi và văn bản
XPS. Việc hiển thị văn bản cũng được chăm chút hơn khi WPF tập trung vào việc nâng
cao chất lượng text hiển thị, giúp việc đọc chữ trên máy tính trở lên dễ hơn.
4
1.2.3. Giải pháp kỹ thuật
Như đã nói ở trên, WPF có hỗ trợ một định dạng văn bản là XPS. Dạng văn bản này xây
dựng cơ sở văn bản bất động của WPF. XPS là một định dạng mở theo đặc tả XML, có
khả năng sử dụng trên nhiều nền tảng khác nhau, được thiết kế nhằm tạo thuận lợi cho
việc chia sẻ, in ấn và lưu trữ văn bản. Trong WPF, văn bản XPS được hiển thị bằng
Document Viewer
Document Viewer là một phần tử có khả năng hiển thị các file văn bản dạng XPS và
PDF. Nó cung cấp sẵn rất nhiều phương thức bao gồm các phương thức điều khiển như
chuyển trang ( Previous Page, Next page, Go to page… ), chế độ hiển thị trang, trạng thái
trang, các công cụ như in ấn…
Vì vậy để mở file PowerPoint chúng em lựa chọn giải pháp là dùng các hàm cung cấp sẵn
của Microsoft Office có trong các file .dll để chuyển đổi file từ định dạng PowerPoint
(.PPTX, .PPT) sang .XPS để mở trong Document Viewer.
2. Xây dựng giao diện với XAML
2.1. Layout
Đối với Windows Form các phần tử giao diện được thiết kế dựa trên nguyên tắc bố trí vị
trí tuyệt đối. Khi thay đổi kích thước form, kích thước của các phần tử lại không kéo dãn
cho phù hợp khiến vùng hiển thị chỗ thừa chỗ thiếu. Vì vậy cần lượng lớn code cần thay
đổi khi thay đổi giao diện.
WPF khắc phục được nhược điểm này. Ta có thể sử dụng các phần tử Panel trong việc bố
trí giao diện :
- StackPanel : sắp xếp các phần tử theo thứ tự trước sau
- WarpPanel : sắp xếp các phần tử từ trái sang phải
- DockPanel : cho phép các phần tử bám lên các cạnh của panel
5
Và linh hoạt và quan trọng nhất là Grid. Nó có thể làm mọi nhiệm vụ mà các Panel khác
có thể làm. Grid cho phép phân định các dòng và cột theo dạng một lưới kẻ ô, và sau đó
sẽ sắp đặt các phần tử UI vào các ô tùy ý. Một phần tử được đặt trong Grid sẽ được bố
cục phù hợp hơn khi kích thước form thay đổi.
Trong bài này chúng em sử dụng Grid và StackPanel.
Để định nghĩa một Grid và khai báo các hàng các cột của nó ta sử dụng cấu trúc như sau:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid>
Trong bài ta khai báo một Grid với 3 hàng, 3 cột. Dấu sao (*) để phân định kích thước
theo tỉ lệ hoặc phân định giá trị tuyệt đối về chiều cao hoặc chiều rộng cho hàng và cột.
Để xếp một phần tử UI vào trong Grid ta sử dụng các thuộc tính : Grid.Column="x"
Grid.Row="y". Trong đó x, y là giá trị của các cột và hàng mà phần tử đó nằm trên, x và
y có giá trị bắt đầu bằng 0, tương ứng với cột và hàng đầu tiên.
Để sắp xếp các phần tử lần lượt theo một thứ tự từ trên xuống hoặc từ trái sang phải ta sử
dụng StackPanel. Chẳng hạn trong bài từ trên xuống dưới lần lượt là Menu Document
Viewer Các button điều khiển như Next, Back, Go to page…
<StackPanel Margin="0">
< ! Các phần tử trong StackPanel >
</StackPanel>
6
2.2. Menu
Là phần tử đầu tiên nằm trong StackPanel. Do giao diện chỉ cần đơn giản nên chỉ có 2
chức năng là : Gọi sự kiện mở một hộp thoại File của Windows "mn_OpenFile_Click" ,
và một phương thức để đóng ứng dụng "mn_ExitApp_Click".
<Menu Height="22" Name="MainMenu" VerticalAlignment="Top">
<MenuItem Header="File" Name="mn_File">
<MenuItem Header="Open" Name="mn_OpenFile"
Click="mn_OpenFile_Click"></MenuItem>
<Separator/>
<MenuItem Header="Exit" Name="mn_ExitApp"
Click="mn_ExitApp_Click"></MenuItem>
</MenuItem>
</Menu>
2.3. Document Viewer
Được đặt trong một Grid (định nghĩa trên 2.1) nhằm mục đích giúp cho file đọc được
luôn nằm tại vị trí chính giữa của Form.
Document Viewer trong bài này là phần tử mặc định của WPF, chỉ được chỉnh sửa một
chút ít trong phần Resources. Chúng ta cũng có thể định nghĩa lại hoàn toàn giao diện của
nó trong file App.xaml (Xem thêm tại phần tài liệu tham khảo [5] )
<DocumentViewer Grid.Column="1"
Grid.Row="0" Name="myDocument" Margin="0"
MaxPagesAcross="1" Zoom="100"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
KeyDown="OnKeyPress"
ScrollViewer.IsDeferredScrollingEnabled="False">
<! ẩn toolbar >
<DocumentViewer.Resources>
7
<Style TargetType="ToolBar">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</Style>
</DocumentViewer.Resources>
</DocumentViewer>
Các thuộc tính được cài đặt là : Ẩn tất cả các thanh cuộc ngang và dọc của trình xem giúp
chương trình trông giống một chương trình trình chiếu Slide hơn là một chương trình đọc
một văn bản (word, adobe reader…). Ẩn thanh công cụ mặc định WPF, thanh này bao
gồm các nút phóng to, thu nhỏ, in tài liệu…
Margin được gán giá trị 0 làm cho kích thước của Document Viewer bằng với kích thước
Form.
2.4. Các button điều khiển
Chúng ta sẽ tạo ra 4 nút điều khiển bao gồm Next, Back, First Page, Last Page tương ứng
với 4 nhiệm vụ. Bên cạnh đó là ô text box cho phép nhập giá trị trang cần “Go to page”
và một nhãn label hiển thị “page number” đang xem.
Do 4 phím trên được bố trí ở giữa đồng thời Go to page xếp tại lề trái, Page number xếp
tại lề phải nên ta sẽ sử dụng đan xen giữa StackPanel và Grid.
<Grid Grid.Column="1" Grid.Row="1" Margin="0,20,0,0"
Name="grid_Control" KeyDown="OnKeyPress">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
8
< ! Nhãn page number được đưa vào một stack và căn lề phải >
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal"
Grid.Column="2" Grid.Row="0">
< ! Xếp các nhãn Page number vào đây >
</StackPanel>
< ! Các nhãn và ô text box go to page được căn lề trái >
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal"
Grid.Column="0" Grid.Row="0">
< ! . . . >
</StackPanel>
< ! Tương tự với các button next, back… được xếp vào giữa >
</Grid>
Sau khi hoàn thành tất cả các phần trên chúng ta được một giao diện đơn giản sau:
9
3. Các phương thức và sự kiện
3.1. OpenFile Dialog
OpenFile Dialog là phương thức tạo một hộp thoại File, cho phép người dùng truy cập tới
một file tại một vị trí tương tự như Windows Explorer. Để
Ở đây ta sẽ mở một hộp thoại khi kích chuột vào menu Open và tạo ra một sự kiện có tên
là mn_OpenFile_Click.
//tạo một đối tượng mới thuộc lớp Win32.OpenFileDialog
Microsoft.Win32.OpenFileDialog openFile = new
Microsoft.Win32.OpenFileDialog();
//bộ lọc file powerpoint
openFile.Filter = "MS PowerPoint (.pptx, .ppt)|*.pptx;*.ppt";
//mở hộp thoại
Nullable<bool> result = openFile.ShowDialog();
if(result==true) //nếu thành công
{
//lưu đường dẫn của file vừa chọn vào biến string
string filename = openFile.FileName;
}
Vậy kết quả của phương thứ trên là đường dẫn file cần mở. Sau đây là cách mở một file
PowerPoint
3.2. Chuyển đổi file PowerPoint sang XPS
Đầu tiên ta phải thêm thư viện hàm của Office bằng cách Add Reference, sau đó chọn các
file .dll như Microsoft.Office.Core và Microsoft.Office.Interop.PowerPoint và khai báo
sử dụng chúng mã nguồn.
10
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using Microsoft.Office.Core;
PowerPoint ở đây là cách viết gọn lại cho thay namespace Microsoft.Office.Interop
.PowerPoint;
Ta tạo một hàm có chức năng chuyển đổi file:
XpsDocument Convert(string ppName, string xpsName)
Hàm này sẽ nhận 2 tham số đầu vào là đường dẫn của file powerpoint và đường dẫn của
file XPS, và trả về một XpsDocument.
//khởi tạo một PowerPoint Apllication mới
PowerPoint.Application app = new PowerPoint.Application();
//Mở App
app.Presentations.Open(ppName, MsoTriState.msoFalse, MsoTriState.msoFalse,
MsoTriState.msoFalse);
PowerPoint.Presentation pre = app.Presentations[app.Presentations.Count];
Các tham số MsoTriState.msoFalse quy định một số thuộc tính của ứng dụng PowerPoint
được gọi lên ở câu trên chẳng hạn như ẩn cửa số của app…
Sau khi gọi được App, ta chuyển đổi file bằng câu lệnh:
pre.ExportAsFixedFormat(xpsName, PowerPoint.PpFixedFormatType.ppFixedFormatTypeXPS);
Câu này có chức năng tương tự như chức năng Save As của PowerPoint. Nó thực hiện
chuyển đổi file sang dạng XPS và lưu vào file có đường dẫn xpsName.
Sau khi chuyển đổi thành công, đóng App PowerPoint lại và tạo một đối tượng
XpsDocument.
app.Quit();
pre.Close();
XpsDocument xpsDoc = new XpsDocument(xpsName, FileAccess.Read);
11
File XPS được tạo ra có thuộc tính chỉ đọc.
Trong trường hợp chuyển đổi thất bại, chúng ta đưa một tin nhắn báo cho người dùng
bằng ngoại lệ:
catch
{
MessageBox.Show("Chuyển đổi thất bại!");
}
3.3. Mở file XPS với DocumentViewer
Việc mở file XPS vẫn nằm trong sự kiện nút Open trên menu được click.
Trước tiên ta tạo một file xps tạm thời tại chính đường dẫn của file PowerPoint bằng cách
sử dụng lớp System.IO.Path.
xpsDocName =
String.Concat(System.IO.Path.GetDirectoryName(openFile.FileName),
"\\",
System.IO.Path.GetFileNameWithoutExtension(openFile.FileName), ".xps");
Sau đó tiến hành chuyển đổi file PowerPoint sang XPS bằng việc gọi phương thức
Convert đã tạo ở phần 3.2.
Doc = Convert(filename, xpsDocName);
Mở file đó bằng DocumentViewer
myDocument.Document = Doc.GetFixedDocumentSequence();
Thiết lập các trạng thái của Document:
Hiển thị toàn trang trên giao diện của DocumentViewer:
myDocument.FitToMaxPagesAcross();
Hiển thị Page Number đang mở lên trên giao diện
12
lb_PageNumberValue.Content = myDocument.MasterPageNumber.ToString();
3.4. Xóa file tạm
Như đã nói, việc đọc file PowerPoint ở đây thực chất gián tiếp của file XPS, vì vậy sau
khi đọc một file ta phải xóa file tạm .XPS vừa tạo ra, nếu không khi đóng ứng dụng sẽ có
một file .XPS sẽ nằm cùng dùng với file PowerPoint gốc gây chiếm tài nguyên máy.
Đối với các tài liệu dạng khác, khi được mở bởi DocumentViewer để đóng nó và xóa nó
đi ta chỉ cần thực hiện đơn giản như sau: Đưa trạng thái của DocumentViewer về null và
dùng phương thức File.Delete của System.IO.
Tuy nhiên với XPS lại không thể làm như vậy.
Trước tiên cần đóng System.IO.Packaging.Package từ nơi mà chúng ta vừa mở tài liệu
với XpsDocument. Việc đóng Package sẽ khóa file và cho phép chúng ta xóa nó. Đương
nhiên là việc xóa chỉ cần thiết khi có một file XPS được mở trước đó
if(xpsDocName!=null)
{
myXpsUri = Doc.Uri;
var theXpsPackage =
System.IO.Packaging.PackageStore.GetPackage(myXpsUri);
theXpsPackage.Close();
System.IO.Packaging.PackageStore.RemovePackage(myXpsUri);
File.Delete(xpsDocName);
}
Việc xóa file phải được thực hiện khi đóng ứng dụng, khi mở một file mở trong khi đọc
một file khác.
13
3.5. Các phương thức điều khiển button
DocumentViewer cung cấp sẵn các phương thức cho phép thực hiện các chức năng đơn
giản như chuyển trang, go to page… Đa phần chỉ cần một câu lệnh rất đơn giản.
Trước hết là chuyển trang khi click chuột vào các button trên giao diện. Khi xảy ra các sự
kiện tương ứng với mỗi button, chúng ta gọi các phương thức sau:
Xem trang kế tiếp: myDocument.NextPage();
Xem trang trước : myDocument.PreviousPage();
Xem trang đầu tiên : myDocument.FirstPage();
Xem trang cuối : myDocument.LastPage();
Để thực hiện các phương thức trên khi nhấn các phím Next, Back, Up, Down trên bàn
phím máy tính ta phải sự dụng một sự kiện là KeyDown. Sự kiện này xảy ra khi một
phím được nhấn. Nó sẽ kiểm tra phím được nhấn có nằm trong số các phím trên không.
Nếu có thì sẽ thực hiện các phương thức đã nói ở trên.
Ở đây ta sẽ cho 2 phím Next và Down có cùng chức năng; tương tự với 2 phím Back và
Up
private void OnKeyPress(object sender, KeyEventArgs e)
{
if(e.Key==Key.Right||e.Key==Key.Down)
{
myDocument.NextPage();
}
else if(e.Key==Key.Left||e.Key==Key.Up)
{
myDocument.PreviousPage();
}
else
{
//Nothing
}
}
14
Một phương thức chuyển trang tiếp là Go To Page, cho phép người dùng nhập vào một
trang bất kỳ và chuyển đến trang đó sau khi nhấn phím Enter trên bàn phím hoặc nhấp
chuột vào Button bên cạnh.
Tương tự như ở trên, chúng ta vẫn dùng sự kiện KeyDown để bắt sự kiện khi nhấn phím
Enter.
private void tb_GoToPage_KeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter)
{
if (tb_GoToPage.Text != "")
{
if(int.Parse(tb_GoToPage.Text)>myDocument.PageCount)
{
MessageBox.Show("Phiền bạn nhập vào số trang nhỏ hơn " +
myDocument.PageCount);
}
else
myDocument.GoToPage(int.Parse(tb_GoToPage.Text));
}
else
{
//Nothing
}
}
}
Trong trường hợp nhập vào số trang không thỏa mãn thì giao diện sẽ hiện nên một thông
báo cho người dùng.
Việc thực hiện chuyển trang được thực hiện tương tự khi nhấp chuột vào button với sự
kiện: bt_GoToPage_Click(object sender, RoutedEventArgs e)
15
3.6. Cập nhật trạng thái hiển thị trang
Với mục đích là mỗi lần thực hiên một thao tác như chuyển trang…người dùng chỉ xem
được một slide (tương tự như PowerPoint) chứ không phải dạng cuộn như các tài liệu
khác (tương tự Word) ta cần thực hiện việc kiểm tra trạng thái của văn bản đạng hiển thị.
Nếu nó đang ở dạng cuộn thì đưa nó về dạng slide. Đồng thời cập nhật thứ tự của trang
lên trên giao diện.
Để làm được việc này ta sử dụng một Timer. Cứ sau 1s thì kiểm tra lại trạng thái trang tài
liệu:
private void MainWD_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Threading.DispatcherTimer myTimer = new
System.Windows.Threading.DispatcherTimer();
myTimer.Tick += myTimer_Tick;
myTimer.Interval = new TimeSpan(0, 0,1);
myTimer.Start();
}
Timer sẽ được gọi ngay từ khi ứng dụng khởi động. Cứ sau một giây nó sẽ thực hiện hàm
myTimer_Tick. Hàm này cập nhật số thứ tự trang và chỉ cho phép hiển thị một trang slide
trên ô hiển thị
void myTimer_Tick(object sender, EventArgs e)
{
if (xpsDocName == null)
{
//nothing
}
else
{
lb_PageNumberValue.Content = myDocument.MasterPageNumber.ToString();
16
myDocument.FitToMaxPagesAcross();
}
}
Khi thay đổi kích thước form, có một vấn đề là DocumentViewer không tự dãn ra như
các phần tử khác. Vì vậy cần sử dụng một sự kiện đó là : MainWD_SizeChanged nhằm
thay đổi kích thước:
myDocument.Height = MainWD.ActualHeight - 120;
myDocument.Width = MainWD.ActualWidth;
Kích thước chỉ thay đổi khi sử dụng thuộc tính ActualHeight và ActualWidth. Nếu chỉ sử
dụng MainWD.Height và MainWD.Width thì không được.
17
4. Tài liệu tham khảo
[1]
[2]
[3]
[4] Pro WPF 4.5 in C# (4
th
edition) – Matthew MacDonald
[5] Cấu hình DocumentViewer :