TServerSocket điều khiển server socket connections trong TCP/IP server. TServerSocket sẽ thiết lập kết nối với một máy khác khi máy này ra yêu cầu. Server socket có thể kết nối đến một số client và bạn có thể giao tiếp với các client này.
Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn GIỚI THIỆU THREAD TRONG DELPHI .3 1.1 THREAD LÀ GÌ? 1.2 ỨNG DỤNG CỦA THREAD 1.3 SỬ DỤNG TTHREAD TRONG DELPHI 1.3.1 Các method đáng ý viết Thread .4 1.3.2 Các property đáng ý viết Thread 1.3.3 Tranh chấp liệu viết multi-thread 1.3.4 Sử Dụng Critical Section chương trình GIAO TIẾP GIỮA CÁC MÁY MƠ HÌNH CLIENT/SERVER 2.1 TCLIENTSOCKET .9 2.1.1 Ghi liệu đến server 10 2.1.2 Đọc liệu từ server 10 2.2 TCLIENTWINSOCKET 10 2.3 TSERVERSOCKET 11 2.3.1 Truyền liệu đến Client 12 2.3.2 Đọc liệu từ client 12 2.3.3 Bạn biết xác Client thứ gửi liệu đến server socket 13 2.4 TSERVERWINSOCKET 13 2.4.1 Lắng nghe yêu cầu kết nối Client 13 2.4.2 Quản lý dãy client socket kết nối với server socket .13 2.5 TSERVERCLIENTWINSOCKET .14 GIỚI THIỆU CHƯƠNG TRÌNH 14 3.1 NỘI DUNG VÀ Ý NGHĨA CHƯƠNG TRÌNH 14 3.2 CÁC VẤN ĐỀ CHÍNH CẦN GIẢI QUYẾT 18 3.2.1 Tổ chức liệu chương trình 18 3.2.2 Kết nối cho client 20 3.2.3 Hủy kết nối cho client 20 3.2.4 Tranh chấp liệu 21 3.2.5 Dùng thread để phân chia CPU cho thao tác client 21 3.3 CÁC CHỨC NĂNG CHO NGƯỜI QUẢN LÝ 21 3.3.1 Tìm kiếm nhà 22 3.3.2 Lấy thông tin nhà 23 3.3.3 Thêm thông tin nhà 25 3.3.4 Xóa thơng tin nhà 26 3.3.5 Cập nhật thông tin nhà 27 3.3.6 Thống kê số nhà cho thuê .29 3.3.6.1 Đếm số nhà cho thuê .30 3.3.6.2 Đưa nhà hết hạn cho thuê danh sách nhà cho thuê 31 3.3.7 Thống kê số nhà bán .34 3.3.7.1 Đếm số nhà bán .35 3.4 CÁC CHỨC NĂNG CHO NGƯỜI CẬP NHẬT THÔNG TIN NHÀ 36 3.4.1 Tìm kiếm nhà 36 3.4.2 Lấy thông tin nhà 37 3.4.3 Cập nhật thông tin nhà 37 3.4.4 Thêm thông tin nhà 38 3.4.5 Xóa thơng tin nhà 38 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -3.5 CÁC CHỨC NĂNG CHO MỘT KHÁCH HÀNG 39 3.5.1 Lấy thông tin nhà 39 3.5.2 Tìm kiếm nhà 39 3.5.3 Tìm kiếm theo điều kiện 40 3.5.4 Đăng ký thuê nhàø .45 3.5.5 Đăng ký mua nhà 48 3.6 MÃ CHƯƠNG TRÌNH KINH DOANH NHÀ ĐẤT TRÊN MẠNG CLIENT/SERVER 51 3.6.1 Nha.dpr 51 3.6.2 Nhaf.pas .52 3.6.3 ConectDlg.pas 74 3.6.4 Findf.pas .77 3.6.5 HomeInfo.pas .81 3.6.6 HomeTools.pas .84 3.6.7 Informf.pas 101 3.6.8 InputThuef.pas 103 3.6.9 MytdRTF.pas 105 3.6.10 MyThread.pas 109 3.6.11 RepThuef.pas 125 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn Giới thiệu Thread Delphi 1.1 Thread gì? Tính Thread cho phép chương trình xử lý đồng thời nhiều cơng việc Chẳng hạn chương trình Go!Zilla Ver 3.2 Copyright © 1997-98 Gizmonet, lúc download nhiều file từ nhiều website khác Nó cịn cho người dùng định độ ưu tiên cho thread Bạn dùng BorlandC, Delphi, Cbuilder, Visual C để viết nên chương trình có tính thread Nhưng dù bạn lập trình ngơn ngữ nữa, phải sử dụng hàm API Microsoft cung cấp CreateThread, SetThreadPriority cách trực tiếp gián tiếp 1.2 Ứng dụng Thread Thread sử dụng nhiều lĩnh vực đồ họa (xử lý nhiều hình ảnh lúc), trị chơi (làm nhân vật trò chơi thread), truyền tin (tín hiệu xuất xử lý tức thời) Thread làm cho chương trình trở nên đơn giản, dễ hiểu ta phải viết chương trình địi hỏi xử lý đồng thời nhiều cơng việc 1.3 Sử dụng TThread Delphi Sử dụng TThread Delphi để viết nên chương trình có tính Thread dễ Cấu trúc unit có sử dụng Thread sau : Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn unit Unit1; interface uses Classes; type TMyThread = class(TThread) private { Private declarations } protected procedure Execute; override; end; implementation { TMyThread } procedure TMyThread.Execute; begin { phần mã có tính Thread đặt đây} end; end Một điều quan trọng cần lưu ý viết Thread đối tượng hay hàm nằm thư viện VCL Delphi phải gọi phương pháp Synchronize Ví dụ : Synchronize(UpdateCaption); Với UpdateCaption : procedure TMyThread.UpdateCaption; begin Form1.Caption := 'Updated in a thread'; end; 1.3.1 Các method đáng ý viết Thread * Constructor Create(CreateSuspended: Boolean); Constructor Create để khởi tạo đối tượng Thread Nếu CreateSuspended = False, Execute gọi Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn Nều CreateSuspended = True, Execute không gọi Resume gọi * Destructor Destroy; override; Destructor Destroy hủy đối tượng thread giải phóng nhớ chiếm giữ * Procedure DoTerminate; virtual; DoTerminate làm cho thread gọi kiện OnTerminate * Procedure Execute; virtual; abstract; Procedure Execute method abstract phải override lớp Nó chứa mã bắt đầu Thread * Procedure Resume; Procedure Resume tiếp tục gọi thread tạm ngưng * Procedure Suspend; Procedure Suspend tạm ngưng thread chạy * Procedure Synchronize(Method: TThreadMethod); Procedure Synchronize thực method dùng thư viện VCL * Procedure Terminate; Procedure Terminate hiệu cho thread dừng cách gán property Terminated True Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn 1.3.2 Các property đáng ý viết Thread * property FreeOnTerminate: Boolean; property FreeOnTerminate định cho đối tượng thread tự động giải phóng nhớ FreeOnTerminate = True * property Handle: Thandle; property Handle handle thread * property Priority: TThreadPriority; property Priority xác định độ ưu tiên thread khác tiến trình TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical); + tpIdle : Chỉ thực hệ thống Windows rảnh rỗi, khơng ngắt ngang đối tượng thread khác để chạy + tpLowest : Mức độ ưu tiên điểm so với bình thường + tpLower : Mức độ ưu tiên điểm so với bình thường + tpNormal: Mức độ ưu tiên bình thường + tpHigher : Mức độ ưu tiên điểm so với bình thường + tpHigher : Mức độ ưu tiên điểm so với bình thường + tpHighest : Mức độ ưu tiên điểm so với bình thường + tpTimeCritical : Mức độ ưu tiên cao * property Suspended: Boolean; property Suspended định thread tạm ngưng true * property Terminated: Boolean; property Terminated định thread yêu cầu dừng true * property ThreadID: THandle; property ThreadID nhận biết cho đối tượng thread xuyên suốt hệ thống ThreadID khác property Handle 1.3.3 Tranh chấp liệu viết multi-thread Khi bạn viết chương trình multi-threaded, có trường hợp thread truy cập đến vùng liệu, chẳng hạn file, điều làm cho file bị hư Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn máy bạn bị treo Để giải vấn đề này, bạn cho thread khác truy cập đến vùng nhớ mà thread hành sửa đổi liệu liệu xử lý xong Critical sections thiết kế mà phần resource dùng riêng biệt tách rời khỏi tiến trình khác Bạn tưởng tượng có hai người song song đường, nhiên xuất cầu hẹp, đủ để người qua Bình thường người nhường đường cho người trước Khi mà người qua cầu người tiếp tục qua cầu họ lại tiếp tục song song với Critical sections tương tự việc qua cầu Bạn nhìn hình đây, hai thread (mũi tên màu cyan) chạy tiến trình đơn (vùng màu đen), thread chạy đến critical sections (vùng màu xanh dương), thread nhường cho thread qua Trong thực tế, thread đến critical sections, tạo cờ hiệu cho thread khác không liên lạc với data Để thực critacal sections mã chương trình viết Borland Delphi, bạn làm dấu khối thread mà truy cập đến vùng nhớ chung hàm EnterCriticalSection LeaveCriticalSection Điều đầu tiên, chương trình, bạn phải định nghĩa critical nhớ Điều thực cách gọi hàm InitializeCriticalSection Hàm khai báo sau: procedure InitializeCriticalSection(var lpCriticalSection: TRTLCriticalSection); stdcall; InitializeCriticalSection lấy tham số kiểu TRTLCriticalSection, mà trường lưu trữ thơng tin critical section Bạn không cần quan tâm cấu trúc nó, bì chẳng cần thao tác Hãy khai báo biến tồn cục kiểu TRTLCriticalSection Sau làm critical xong, hủy hàm DeleteCriticalSection Cũng giống InitializeCriticalSection, hàm có tham số kiểu TRTLCriticalSeciont Trong trường hợp này, hai tham số biến DeleteCriticalSection InitializeCriticalSection Trong chương trình bạn gõ vào lệnh sau: Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn unit myCritical; Interface var CritSect : TRTLCriticalSection; … Implementation … initialization InitializeCriticalSection(CritSect); finalization DeleteCriticalSection(CritSect); end 1.3.4 Sử Dụng Critical Section chương trình Đặt critical section để dùng thread dễ Bạn cần xem đoạn mã ví dụ biết ngay: procedure TMyThread.ChangeData; begin EnterCriticalSection(CritSect); Các thao tác sửa đổi liệu dùng chung đặt LeaveCriticalSection(CritSect); end; Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn Giao tiếp máy mơ hình Client/Server Trong đề tài thực tập này, ta dùng ngơn ngữ lập trình Delphi để giao tiếp máy qua mơ hình Client/Server, cụ thể sử dụng control : TClientSocket, ClientWinSocket, TServerSocket, TServerWinSocket Hình liệt kê lớp socket control: 2.1 TClientSocket TClientSocket dùng để kết nối đến Server Socket Để sử dụng control này, bạn nên làm thao tác sau đây: (1) (2) (3) (4) (5) Viết mã cho OnRead Event Định Address property đến Server address Định Port giá trị Port Property TServerSocket muốn kết nối Định ClientType property đến ctNonBlocking Gọi Open method để kết nối đến remote Server Ta nói thêm ClientType property Nếu ClientType = ctNonBlocking, chương trình đọc hay ghi liệu đến socket, chương trình thực lệnh I/O tiếp tục thực chương trình thao tác I/O chưa thực xong Nếu ClientType = ctBlocking, chương trình tạm không chạy tiếp mà chờ thao tác I/O thực xong Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn Trong chương trình này, ta cho ClientType = ctNonBlocking 2.1.1 Ghi liệu đến server Khi bạn muốn gửi liệu đi, dùng lệnh tương tự sau: MyClientSocket.Socket.SendText("this is a test"); TClientSocket TClientWinSocket Hoặc dùng lệnh: BytesWritten := MyClientSocket.Socket.SendBuf(buf, count); 2.1.2 Đọc liệu từ server Bạn đọc liệu từ Server cách dùng lệnh ReceiveText hay ReceiveBuf đặt OnRead Event procedure TChatForm.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); begin StringData := Socket.ReceiveText; end; 2.2 TClientWinSocket Ta mô tả số hàm quan trọng TClientWinSocket function ReceiveBuf(var Buf; Count: Integer): Integer; ReceiveBuf đọc liệu từ server socket, số byte đọc người dùng định Dữ liệu đọc chứa Buf, giá trị trả số byte thực đọc function ReceiveText: string; Dùng ReceiveText để đọc chuỗi từ server socket 10 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{TMuaNhaThread} constructor TMuaNhaThread.Create; begin FreeOnTerminate := True; FIndex := Index; inherited Create(False); end; procedure TMuaNhaThread.DoThread; begin ChatForm.MuaNha(FIndex); end; procedure TMuaNhaThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; 115 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{TThueNhaThread} constructor TThueNhaThread.Create; begin FreeOnTerminate := True; FIndex := Index; FNgayDauThue := NgayDauThue; FNgayCuoiThue := NgayCuoiThue; inherited Create(False); end; procedure TThueNhaThread.DoThread; begin ChatForm.ThueNha(FIndex, FNgayDauThue, FNgayCuoiThue); end; procedure TThueNhaThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure TThueNhaThread.DoTerminate; begin inherited; end; 116 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{THomeGetThread} constructor THomeGetThread.Create; begin FreeOnTerminate := True; FIndex := Index; FIsServer := IsServer; FClient := Client; inherited Create(False); end; procedure THomeGetThread.DoThread; var x : xxType; begin ChatForm.ffHome := ChatForm.HomeData.HomeGet(FIndex); if not FIsServer then begin FillChar(x, sizeof(x), 0); StrCopy(x.mess, idSetItem); x.Home := ChatForm.ffHome; ChatForm.ServerSocket.Socket.Connections[FClient].SendBuf(x, sz); end; end; procedure THomeGetThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure THomeGetThread.DoTerminate; begin inherited; end; 117 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{THomeSearchTextThread} constructor THomeSearchTextThread.Create; begin FreeOnTerminate := True; FName := Name; FIsServer := IsServer; FClient := Client; inherited Create(False); end; procedure THomeSearchTextThread.DoThread; var x : xxType; found : boolean; begin ChatForm.fIndex := ChatForm.HomeData.HomeSearch(Pchar(FName), found); if not FIsServer then begin FillChar(x, sizeof(x), 0); StrCopy(x.mess, idSetIndex); x.index := ChatForm.fIndex; ChatForm.ServerSocket.Socket.Connections[FClient].SendBuf(x, sz); end end; procedure THomeSearchTextThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure THomeSearchTextThread.DoTerminate; begin inherited; end; 118 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{THomeGetFilterThread} constructor THomeGetFilterThread.Create; begin FreeOnTerminate := True; FIndex := Index; FIsServer := IsServer; FClient := Client; inherited Create(False); end; procedure THomeGetFilterThread.DoThread; var x : xxType; begin ChatForm.ffHome := ChatForm.HomeData.HomeGet(FIndex); if not FIsServer then begin FillChar(x, sizeof(x), 0); StrCopy(x.mess, idSetItemfilter); x.Home := ChatForm.ffHome; ChatForm.ServerSocket.Socket.Connections[FClient].SendBuf(x, sz); end; end; procedure THomeGetFilterThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure THomeGetFilterThread.DoTerminate; begin inherited; end; 119 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{THomeGetDataThread} constructor THomeGetDataThread.Create; begin FreeOnTerminate := True; FIndex := Index; FIsServer := IsServer; FClient := Client; inherited Create(False); end; procedure THomeGetDataThread.DoThread; var x : xxType; begin ChatForm.fHome := ChatForm.HomeData.HomeGet(FIndex); if not FIsServer then begin FillChar(x, sizeof(x), 0); StrCopy(x.mess, idSetData); x.Home := ChatForm.fHome; ChatForm.ServerSocket.Socket.Connections[FClient].SendBuf(x, sz); end; end; procedure THomeGetDataThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure THomeGetDataThread.DoTerminate; begin inherited; end; 120 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{ TFindThread } constructor TFindThread.Create; begin FreeOnTerminate := True; FFind := Find; FClient := Client; inherited Create(False); end; procedure TFindThread.DoThread; var x : xxType; begin FFilterCount := ChatForm.HomeData.HomeGetCount; Getmem(FFilter, FFilterCount * sizeof(longint)); ChatForm.HomeData.HomeFind(FFind.ThueBan, FFind.NgoaiNoiThanh, FFind.TriGiaMin, FFind.TriGiaMax, FFind.DienTichMin, FFind.DienTichMax, FFilter, FFilterCount); FillChar(x, sizeof(x), 0); x.index := FFilterCount; StrCopy(x.mess, idFindResult); move(FFilter^, x.Home, FFilterCount * sizeof(longint)); ChatForm.ServerSocket.Socket.Connections[FClient].SendBuf(x, sz); Freemem(FFilter); end; procedure TFindThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure TFindThread.DoTerminate; begin inherited; end; 121 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{TDeleteThread} constructor TDeleteThread.Create; begin FreeOnTerminate := True; FIndex := Index; inherited Create(False); end; procedure TDeleteThread.DoThread; begin ChatForm.DeleteNha(FIndex); end; procedure TDeleteThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; procedure TDeleteThread.DoTerminate; begin inherited; end; {THomeRentGetDataThread} constructor THomeRentGetDataThread.Create; begin FreeOnTerminate := True; FIndex := Index; inherited Create(False); end; procedure THomeRentGetDataThread.DoThread; begin RepThueForm.fHome := ChatForm.HomeData.HomeGetRent(FIndex); end; procedure THomeRentGetDataThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; 122 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -{ TUnRentThread } constructor TUnRentThread.Create; begin FreeOnTerminate := True; FIndex := Index; inherited Create(False); end; procedure TUnRentThread.DoThread; var i, count : integer; fHome : THomeInfo; begin if ChatForm.HomeData.HomeUnRent(FIndex) then begin Count := ChatForm.homeData.HomeGetCount; for i := to ChatForm.ServerSocket.Socket.ActiveConnections - ChatForm.SendMessageToClient( ChatForm.ServerSocket.Socket.Connections[i], idSetVLBNumItems, Count, fHome); end; end; procedure TUnRentThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; {THomeSellGetDataThread} constructor THomeSellGetDataThread.Create; begin FreeOnTerminate := True; FIndex := Index; inherited Create(False); end; procedure THomeSellGetDataThread.DoThread; begin RepThueForm.fHome := ChatForm.HomeData.HomeGetSell(FIndex); end; procedure THomeSellGetDataThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); 123 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -end; {THomeRentCountThread} constructor THomeRentCountThread.Create; begin FreeOnTerminate := True; inherited Create(False); end; procedure THomeRentCountThread.DoThread; begin RepThueForm.fHomeRentCount := ChatForm.HomeData.HomeGetCountRent; end; procedure THomeRentCountThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; {THomeSellCountThread} constructor THomeSellCountThread.Create; begin FreeOnTerminate := True; inherited Create(False); end; procedure THomeSellCountThread.DoThread; begin RepThueForm.fHomeSellCount := ChatForm.HomeData.HomeGetCountSell; end; procedure THomeSellCountThread.Execute; begin EnterCriticalSection(CritSect); Synchronize(DoThread); LeaveCriticalSection(CritSect); end; end 124 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn 3.6.11 RepThuef.pas Khung trao đổi để thị danh sách nhà cho thuê mướn (* repthuef.pas Written by Le Tuan *) unit repthuef; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls, VLB, HomeTools, myThread, Tranbtn, ShadowForm, MyDialog, informf, QFButton; type TRepThueForm = class(TShadowForm) VLB: TVLB; Bevel2: TBevel; Bevel3: TBevel; RichEdit: TRichEdit; Bevel4: TBevel; Label1: TLabel; AdminLTBtnUnThue: TLTBtn; AdminLTBtnCount: TLTBtn; LabelName: TLabel; QFButton1: TQFButton; Bevel1: TBevel; ImageBan: TImage; ImageThue: TImage; procedure VLBGetItem(Sender: TObject; Index: Integer; var ItemString: String); procedure AdminLTBtnUnThueClick(Sender: TObject); procedure FormPaint(Sender: TObject); procedure VLBClick(Sender: TObject); procedure FormActivate(Sender: TObject); procedure AdminLTBtnCountClick(Sender: TObject); procedure QFButton1Click(Sender: TObject); private procedure ShowData; function TestTLTBtn(p : TPoint) : boolean; procedure wmNcHitTest(var Msg : TwmNcHitTest); message wm_NcHitTest; public fHome : THomeInfo; isThue : Boolean; fHomeRentCount : longint; 125 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -fHomeSellCount : longint; end; var RepThueForm: TRepThueForm; implementation {$R *.DFM} uses nhaf, mytdrtf; procedure TRepThueForm.VLBGetItem(Sender: TObject; Index: Integer; var ItemString: String); begin if (index < 0) then exit; if isThue then with THomeRentGetDataThread.Create(Index) WaitFor else with THomeSellGetDataThread.Create(Index) WaitFor; ItemString := fHome.TenNha; end; procedure TRepThueForm.AdminLTBtnUnThueClick(Sender: TObject); var index : longint; begin index := VLB.ItemIndex; if (index < 0) or (self = nil) then exit; if ShowInfo( 'Bân c¢ mu–n Ÿa nh… n…y v‹ danh sÿch nh… cho thuˆ kh“ng?', true) mrOK then Exit; with TUnRentThread.Create(index) WaitFor; VLB.NumItems := ChatForm.homeData.HomeGetCountRent; ChatForm.VLB.NumItems := ChatForm.homeData.HomeGetCount; end; procedure TRepThueForm.FormPaint(Sender: TObject); begin ChatForm.PaintBack(Canvas, ChatForm.Image1.Picture.Bitmap); end; 126 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -procedure TRepThueForm.ShowData; var rtf : TMemoryStream; begin LabelName.Caption := fHome.TenNha; rtf := TMemoryStream.Create; RecToRTF(fHome, rtf); RichEdit.Lines.LoadFromStream(rtf); rtf.Free; end; procedure TRepThueForm.VLBClick(Sender: TObject); var index : longint; begin index := VLB.ItemIndex; if (index < 0) or (self = nil) then begin RichEdit.Clear; Exit; end; if isThue then with THomeRentGetDataThread.Create(Index) WaitFor else with THomeSellGetDataThread.Create(Index) WaitFor; ShowData; end; 127 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -procedure TRepThueForm.FormActivate(Sender: TObject); begin if isThue then begin ImageThue.Visible := true; Caption := 'Th–ng kˆ nh… cho thuˆ'; Label1.Caption := '&Nh… cho thuˆ:'; AdminLTBtnUnThue.Visible := true; AdminLTBtnCount.Hint := 'Th–ng kˆ t™ng s– nh… cho thuˆ'; VLB.NumItems := ChatForm.homeData.HomeGetCountRent; end else begin ImageBan.Visible := true; Caption := 'Th–ng kˆ nh… bÿn'; Label1.Caption := '&Nh… bÿn:'; AdminLTBtnUnThue.Visible := false; AdminLTBtnCount.Hint := 'Th–ng kˆ t™ng s– nh… bÿn'; VLB.NumItems := ChatForm.homeData.HomeGetCountSell; end; VLB.ItemIndex := 0; VLBClick(nil); // NamePanel.Color := rgb(9, 115, 25); end; procedure TRepThueForm.AdminLTBtnCountClick(Sender: TObject); begin if isThue then begin with THomeRentCountThread.Create WaitFor; ShowInfo('C¢ ' + IntToStr(fHomeRentCount) + ' ng“i nh… cho thuˆ.', false); end else begin with THomeSellCountThread.Create WaitFor; ShowInfo('C¢ ' + IntToStr(fHomeSellCount) + ' ng“i nh… bÿn.', false); end end; procedure TRepThueForm.QFButton1Click(Sender: TObject); begin Close; ModalResult := mrCancel; end; 128 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy Thoại Nam – Sinh Viên Lê Tuấn -function TRepThueForm.TestTLTBtn(p : TPoint) : boolean; var i : integer; begin result := false; for i := to ControlCount - begin if (Controls[i] is TLTBtn) and (PtInRect((Controls[i] as TLTBtn).BoundsRect, p)) then Exit; if (Controls[i] is TQFButton) and (PtInRect((Controls[i] as TQFButton).BoundsRect, p)) then Exit; end; result := true; end; procedure TRepThueForm.wmNcHitTest(var Msg : TwmNcHitTest); begin inherited; if TestTLTBtn(ScreenToClient(Point(Msg.Pos.X, Msg.Pos.Y))) then Msg.Result := HTCAPTION; end; end 129 ... đảm nhận 3.3.1 Tìm kiếm nhà Tồn nhà có từ điển (không kể nhà thuê hay bán) liệt kê listbox Danh sách nhà xếp theo alphabet theo tên gợi nhớ nhà 22 Kinh Doanh Nhà Trên Mạng Client/Server – Thầy... sách nhà cho thuê 3.3.6.1 Đếm số nhà cho thuê Bạn đếm có nhà cho thuê cách nhấn nút Đếm Nhà Đã Thuê, khung trao đổi sau sau cho bạn thơng tin có tất nhà cho thuê 30 Kinh Doanh Nhà Trên Mạng Client/Server... 3.3.6 Thống kê số nhà cho thuê Người quản lý thống kê nhà cho thuê Nhấn chuột vào nút Thống Kê Nhà Cho Thuê, khung trao đổi Thống Kê Nhà Cho Thuê đây: 29 Kinh Doanh Nhà Trên Mạng Client/Server