Gửi tin nhắn Delphi. Gửi thư bằng Delphi. Sử dụng tin nhắn trong ứng dụng

Gửi và nhận thư khá đơn giản bằng Delphi. Để gửi thư, chúng ta cần thành phần idSMTP từ trang Khách hàng Indy của bảng thành phần Delphi.

Thành phần này triển khai mọi thứ cần thiết để gửi email qua SMTP (Giao thức truyền thư đơn giản), sử dụng cổng 25, qua đó các lệnh và văn bản thư được gửi. Các bước gửi email như sau:

1) kết nối với máy chủ SMTP trên cổng 25;
2) chuẩn bị nội dung thư, xác định người gửi và người nhận thư;
3) gửi thư đến máy chủ SMTP;

Sau khi đặt thành phần idSMTP trên biểu mẫu, hãy cấu hình nó. Cổng có thể được định cấu hình trong trình kiểm tra đối tượng bằng cách đặt thuộc tính Cổng thành 25 hoặc bạn có thể thực hiện tương tự trong mã chương trình:

IdSMTP1.Port:=25;

Kết nối với máy chủ

Để kết nối với máy chủ SMTP sẽ gửi thư của chúng tôi, bạn cần chỉ định URL của nó; đối với máy chủ mail.ru, việc này được thực hiện như sau:

IdSMTP1.Host:= ′smtp.mail.ru′;

Kết nối đến máy chủ được thực hiện bằng phương thức Connect:


thủ tục Connect(const ATimeout: Integer); ghi đè;

trong đó ATimeout là tham số tùy chọn chỉ định thời gian tối đa tính bằng mili giây để chờ phản hồi từ máy chủ SMTP, sau đó nỗ lực thiết lập kết nối sẽ bị chấm dứt.

Ví dụ,

IdSMTP1.Connect(5000);

Nếu cần có ủy quyền khi kết nối với máy chủ thì giá trị của thuộc tính AuthenticationType phải được đặt thành atLogin, đồng thời trong trình kiểm tra đối tượng, bạn cũng cần xác định thuộc tính Tên người dùng (tên người dùng. Ví dụ: Tên người dùng của hộp thư [email được bảo vệ]- delphi) và Mật khẩu (mật khẩu hộp thư) hoặc thực hiện tương tự theo chương trình:

IdSMTP1.AuthenticationType:=atLogin;
IdSMTP1.Tên người dùng:=′delphi′;
IdSMTP1.Password:='cái gì đó';

IdSMTP1.AuthenticationType:=atNone;

Sau khi sử dụng phương thức Connect, bạn cần phân tích thuộc tính logic Đã kết nối, thuộc tính này nếu kết nối thành công sẽ được đặt thành True. Sau này, bạn có thể gửi tin nhắn bằng phương thức Gửi:

nếu Connected=True thì IdSMTP1.Send(Msg);

Cấu trúc chữ cái

Phương thức Gửi sẽ gửi nội dung thư, là cấu trúc kiểu TIdMessage;

Cấu trúc thông báo được triển khai ở Delphi bởi một thành phần TIdMessage riêng biệt nằm trên bảng thành phần Indy Misc và trông như thế này

TidMessage Cấu trúc TIdMessage được định nghĩa như sau:

Tôi nghĩ mọi thứ đều rõ ràng với chủ đề của tin nhắn. Tài sản

Tên của các tài khoản điện tử mà lá thư được gửi đến được xác định cụ thể. Tên phải được chỉ định bằng dấu phân cách có dạng "," nghĩa là được phân tách bằng dấu phẩy. Ví dụ:

Ví dụ,

Ví dụ,

Thuộc tính Text chứa thông tin từ cả hai thuộc tính. Nội dung của tin nhắn là một đối tượng thuộc loại TStrings:

trong đó Bộ sưu tập là một đối tượng của lớp TIdMessageParts, là một tập hợp các tệp đính kèm email.
hằng số AFileName thuộc loại TFileName - là một chuỗi văn bản thông thường chỉ đường dẫn chính xác đến tệp, ví dụ "C:file.zip", giá trị mặc định là ′′.

Vì vậy, tiếp tục ví dụ của chúng tôi với một dòng như

ở đâu đó như thế này

IdTCPClient1.Host:= "127.0.0.1"; IdTCPClient1.Connect;// đã kết nối IdTCPClient1.Socket.WriteLn("lệnh"); // đã gửi lệnh và nguồn cấp dữ liệu // Đợi phản hồi và đóng kết nối txtResults.Lines.Append(IdTCPClient1.Socket.ReadLn); IdTCPClient1.Disconnect;

trong trường hợp này, lệnh chỉ là văn bản có nguồn cấp dữ liệu dòng. Điều này giúp việc nhận lệnh từ phía bên kia dễ dàng hơn nhiều (chỉ ReadLn). Trong trường hợp chung, bạn cần đưa ra (hoặc sử dụng giao thức làm sẵn).

phía trên nó là một khách hàng. Và bây giờ là máy chủ. Với máy chủ, mọi thứ phức tạp hơn một chút. Rõ ràng là việc một máy chủ phục vụ không chỉ một khách hàng mà nhiều khách hàng là điều bình thường. Và có một số “kế hoạch” cho việc này.

    Cổ điển - một khách hàng - một chủ đề. Lược đồ này dễ viết mã và trực quan. Nó được song song tốt trên các lõi. Nhược điểm là thường rất khó tạo nhiều luồng và điều này hạn chế số lượng máy khách. Đối với các chương trình 32 bit, giới hạn trên là khoảng 1500 (một nghìn rưỡi) luồng cho mỗi quy trình. Nhưng trong trường hợp này, chi phí chung cho việc chuyển đổi chúng có thể “ăn hết” toàn bộ tỷ lệ phần trăm. Đây là sơ đồ được sử dụng trong indy.

    Cách cổ điển thứ hai là tất cả khách hàng trên một luồng. Lược đồ này thường phức tạp hơn về mã hóa, nhưng với cách tiếp cận phù hợp, nó cho phép bạn giữ lại 20-30k “người dùng chậm” mà hầu như không tải kernel. Ưu điểm mạnh mẽ của sơ đồ này là bạn có thể thực hiện mà không cần mutex và các nguyên hàm đồng bộ hóa khác. Lược đồ này được NodeJS và các lớp tiêu chuẩn sử dụng để làm việc với mạng trong Qt.

    Trộn. Trong trường hợp này, một số luồng được tạo, mỗi luồng phục vụ một số lượng khách hàng nhất định. Khó viết mã nhất nhưng cho phép bạn tận dụng tối đa tài nguyên phần cứng.

Nó được thực hiện như thế nào ở Indy. Máy chủ Indy tcp tạo một luồng riêng (TThread) cho mỗi kết nối và công việc tiếp theo với máy khách sẽ diễn ra trong đó. Indy che giấu điều này một cách khéo léo, để người dùng chỉ thực hiện phương thức IdTCPServer.onExecute. Tuy nhiên, như tôi đã nói ở trên, phương pháp này được triển khai trong một luồng riêng biệt và mang tính cá nhân đối với từng khách hàng. Điều này có nghĩa như sau:

  • trong phương pháp này, bạn có thể gọi chế độ ngủ và chỉ một khách hàng sẽ đợi. Tất cả những thứ khác sẽ hoạt động (nhưng nếu bạn gọi chế độ ngủ trong trình xử lý bấm nút thì kết quả sẽ được biết)
    • Tốt hơn là chỉ truy cập các biến toàn cục thông qua các nguyên hàm đồng bộ hóa.
    • Bạn cần truy cập các phần tử gui một cách cẩn thận và chính xác. Tốt hơn hết là không nên thực hiện trực tiếp (một số thành phần cho phép truy cập chúng từ các luồng khác, nhưng bạn cần đọc kỹ tài liệu).
    • Bạn cần truy cập các ứng dụng khách khác thông qua việc chặn (vì nếu hai luồng muốn ghi cho cùng một người dùng thì sẽ không có gì tốt đẹp cả).

Hãy xem một ví dụ rất đơn giản. Chúng tôi đáp ứng bất kỳ yêu cầu nào của khách hàng bằng hiện vật và đóng kết nối (loại máy chủ tiếng vang).

Quy trình TForm1.IdTCPServer1Execute(AContext: TIdContext); var strText: Chuỗi; bắt đầu //Nhận một chuỗi từ máy khách strText:= AContext.Connection.Socket.ReadLn; //Trả lời AContext.Connection.Socket.WriteLn(strText); //Đóng kết nối với người dùng AContext.Connection.Disconnect; kết thúc;

AContext là một đối tượng đặc biệt chứa tất cả thông tin cần thiết về khách hàng. Bản thân idTcpServer chứa danh sách các bối cảnh này và có thể được truy cập. Hãy xem xét một chương trình phát sóng phức tạp hơn. Tức là gửi một tin nhắn cho mọi người

Khách hàng của Var: TList; tôi: số nguyên; bắt đầu // bằng chứng ngu ngốc :) nếu không được chỉ định(IdTCPServer1.Contexts) thì thoát; // lấy danh sách khách hàng và khóa nó. Khách hàng:=IdTCPServer1.Contexts.LockList; try for i:= 0 tới Khách hàng.Count-1 hãy thử //LBuffer thuộc loại TBytes và chứa dữ liệu đã chuẩn bị để gửi // nhưng WriteLn cũng có thể được sử dụng. TIdContext(Clients[i]).Connection.IOHandler.Write(LBuffer); ngoại trừ // bạn cần thêm logic vào đây. Máy khách có thể ngắt kết nối trong quá trình kết thúc; cuối cùng // quan trọng! danh sách phải được mở khóa, nếu không các phương thức khác sẽ không thể đi xa hơn Contexts.LockList IdTCPServer1.Contexts.UnlockList; kết thúc; kết thúc;

indie chứa BytesToString() và ToBytes() để chuyển đổi String và TIdBytes thành nhau.

Danh sách bị khóa để người khác không thể sửa đổi nó. Nếu không, chu trình sẽ trở nên phức tạp hơn nhiều. Và quan trọng nhất, đừng quên mở khóa!

Còn lại một câu hỏi cuối cùng. Cách gửi tin nhắn đến một khách hàng cụ thể. Để làm điều này, bạn cần học cách xác định kết nối. Điều này có thể được thực hiện theo nhiều cách - hãy xem IP/cổng. Nhưng có tốt hơn. IdContext (chính xác hơn là idTask tổ tiên của nó) có thuộc tính Dữ liệu thuộc loại TObject. Bạn có thể viết đối tượng của mình vào đó và lưu trữ tất cả dữ liệu cần thiết ở đó. Một trường hợp sử dụng điển hình sẽ như sau. Khi máy khách vừa kết nối, trường này trống. Khi nó vượt qua quá trình kiểm tra tên-mật khẩu, chúng tôi tạo một đối tượng (của riêng chúng tôi), lưu tên ở đó và ghi nó vào thuộc tính Dữ liệu. Và sau đó, khi bạn cần duyệt qua các máy khách được kết nối, chúng tôi chỉ cần đọc nó. Tất nhiên, nếu có hàng nghìn người dùng, việc xem tất cả người dùng mỗi lần sẽ rất tốn kém. Nhưng làm thế nào để thực hiện điều này một cách tối ưu hơn lại là chủ đề của một bài viết lớn khác.

Trình tự xử lý tin nhắn ở Delphi
Tất cả các lớp Delphi đều có cơ chế xử lý tin nhắn tích hợp được gọi là trình xử lý tin nhắn. Một lớp nhận được một tin nhắn và gọi một trong các tập hợp các phương thức được xác định tùy thuộc vào tin nhắn nhận được. Nếu phương thức tương ứng không được xác định thì trình xử lý mặc định sẽ được gọi. Chi tiết hơn, cơ chế này hoạt động như sau.

Sau khi nhận được tin nhắn, hệ thống tin nhắn VCL sẽ thực hiện rất nhiều công việc sơ bộ để xử lý nó.

Như đã lưu ý ở trên, thông báo ban đầu được xử lý bằng phương thức TApplication.ProcessMessage, phương thức này sẽ chọn nó từ hàng đợi trong vòng lặp thông báo chính. Đồng thời, nó kiểm tra nội dung của trường FOnMessage (trên thực tế, nó kiểm tra sự hiện diện của trình xử lý cho sự kiện OnMessage) và nếu nó không trống thì sẽ gọi trình xử lý cho sự kiện này và nếu trường này trống (Nil), sau đó gọi hàm API DispatchMessage(Msg). Điều này không xảy ra khi gửi tin nhắn.

Nếu trình xử lý sự kiện OnMessage không được xác định thì hàm API DispatchMessage sẽ được gọi để xử lý tin nhắn đã nhận, chuyển tin nhắn đó đến thủ tục cửa sổ chính.

Hãy xem xét chu trình xử lý tin nhắn sau khi nó đến cửa sổ chính của thành phần. Trình tự xử lý tin nhắn được thể hiện trong hình sau:

Có thể thấy tin nhắn được truyền tới MainWndProc, sau đó đến WndProc, rồi đến Dispatch, rồi đến DefaultHandler.

Delphi cung cấp một phương thức phi ảo chính MainWndProc(Var Message: TMessage) cho mỗi cửa sổ thành phần. Nó chứa một khối xử lý ngoại lệ, chuyển cấu trúc thông báo từ Windows sang một phương thức ảo được xác định trong thuộc tính WindowProc. Tuy nhiên, phương pháp này xử lý mọi ngoại lệ xảy ra trong quá trình xử lý tin nhắn bằng cách gọi phương thức HandleException của ứng dụng. Từ thời điểm này trở đi, bạn có thể cung cấp khả năng xử lý thông báo đặc biệt nếu logic của chương trình của bạn yêu cầu. Thông thường tại thời điểm này, quá trình xử lý được sửa đổi để ngăn quá trình xử lý VCL tiêu chuẩn diễn ra.

Theo mặc định, giá trị thuộc tính WindowProc của một đối tượng được khởi tạo theo địa chỉ của phương thức ảo WndProc. Tiếp theo, nếu không có bộ chặn tin nhắn đã đăng ký thuộc loại TWindowHook, WndProc gọi phương thức ảo TObject.Dispatch, sử dụng trường Msg của cấu trúc tin nhắn đến để xác định xem tin nhắn có nằm trong danh sách xử lý tin nhắn cho đối tượng này hay không. Nếu đối tượng không xử lý tin nhắn, danh sách các trình xử lý tin nhắn tổ tiên sẽ được kiểm tra. Nếu cuối cùng một phương thức như vậy được tìm thấy, nó sẽ được gọi; nếu không, phương thức ảo DefaultHandler sẽ được gọi.

Cuối cùng, thông báo đi đến quy trình xử lý thích hợp, tại đó quá trình xử lý dành cho nó sẽ được thực hiện. Sử dụng từ khóa Kế thừa, nó sẽ được gửi tiếp để xử lý ở tổ tiên. Sau đó, thông báo cũng chuyển đến phương thức DefaultHandler, phương thức này xử lý thông báo cuối cùng và chuyển nó tới quy trình DefWindowProc (DefMDIProc) để xử lý Windows tiêu chuẩn.

Xử lý tin nhắn với các thành phần Delphi
Vì vậy, mô tả ngắn gọn về trình tự xử lý thông báo như sau. Tất cả các tin nhắn ban đầu đều đi qua phương thức có địa chỉ được chỉ định trong thuộc tính WindowProc. Theo mặc định đây là phương pháp WndProc. Sau đó, chúng được tách ra và gửi đi theo phương thức tin nhắn riêng. Cuối cùng, chúng hội tụ lại theo phương thức DefaultHandler, nếu chúng không được xử lý trước đó hoặc trình xử lý kế thừa (Được kế thừa) được gọi trong trình xử lý. Vì vậy, các thành phần Delphi có các khả năng sau để xử lý tin nhắn:
a) Trước khi bất kỳ trình xử lý tin nhắn nào nhìn thấy tin nhắn. Trong trường hợp này, bạn cần thay thế địa chỉ phương thức trong thuộc tính WindowProc hoặc thay thế phương thức TControl.WndProc.
Thuộc tính WindowProc được khai báo như sau:

Toure Phương thức TWnd= Thủ tục(Tin nhắn Var: TMessage) Đối tượng;
Tài sản WindowProc: TWndMethod;

Trên thực tế, bằng cách sử dụng thuộc tính WindowProc, bạn có thể tạo một phương thức loại TWndMethod và tạm thời thay thế phương thức ban đầu bằng phương thức đã tạo, tuy nhiên, do địa chỉ phương thức trong thuộc tính WindowProc không được lưu trữ nên trước tiên bạn phải lưu địa chỉ của phương pháp WndProc ban đầu để có thể khôi phục nó sau này.

OldWndProc: TWndMethod;
thủ tục NewWndProc(var Message: TMessage);
thủ tục TForm1.NewWndProc(var Message: TMessage);
var Ch: char;
bắt đầu
nếu message.Msg= WM_MOUSEMOVE thì bắt đầu
Edit1.Text:=’x=’+inttostr(message.LParamLo)+’, y=’+inttostr(message.LParamHi);
kết thúc
khác WndProc(Tin nhắn);
kết thúc;

thủ tục TForm1.FormCreate(Người gửi: TObject);
bắt đầu
OldWndProc:=WindowProc;
kết thúc;

thủ tục TForm1.CheckBox1Click(Người gửi: TObject);
bắt đầu
Nếu CheckBox1.Checked thì WindowProc:= NewWndProc
khác WindowProc:= OldWndProc;
kết thúc;

b) Bên trong phương thức tin nhắn tương ứng.
Hãy đưa ra một ví dụ tương tự khác.
Sử dụng thông báo được gửi đến các thành phần để vẽ lại WMPAINT.

Trong lớp TForml, chúng ta sẽ khai báo phương thức này với mục đích ghi đè nó và trình bày cách triển khai phương thức thông báo bị ghi đè:

Ture TForml=Lớp(TForm)
… // Tất cả các khai báo cần thiết khác
Được bảo vệ
Quy trình WMPaint(Var Msg: TWMPaint); Tin nhắn WM_PAINT; Kết thúc;
Quy trình TForml.WMPaint(Var Msg: TWMPaint); Bắt đầu
Nếu CheckBox1.Checked thì ShowMessage('O6pa6ot message!');
Thừa hưởng;
Kết thúc;

Khi ghi đè các trình xử lý tin nhắn cụ thể, bạn nên gọi Inherited để thực hiện quá trình xử lý tin nhắn cơ bản mà Windows yêu cầu.

c) Sau mỗi phương thức tương ứng với thông báo sẽ thấy nó.

Trong trường hợp này, cần ghi đè DefaultHandler.

thủ tục DefaultHandler(var Message); ghi đè;
thủ tục TForm1.DefaultHandler(var Message);
var i: số nguyên;
bắt đầu
nếu Cardinal(Message)=WM_defh thì
for i:= 0 tới 10 bắt đầu
tiếng kêu bíp;
ngủ(100);
kết thúc
khác
thừa hưởng;
kết thúc;

thủ tục TForm1.Button5Click(Người gửi: TObject);
bắt đầu
SendMessage(Xử lý,WM_defh,0,0);
kết thúc;

Mối quan hệ giữa tin nhắn và sự kiện
Nhiều sự kiện VCL Delphi có liên quan trực tiếp đến thông báo Windows. Hệ thống trợ giúp của Delphi liệt kê những kết quả phù hợp này. Chúng được trình bày trong Bảng 1.

Bảng 1

Sự kiện VCLThông báo WindowsSự kiện VCLThông báo Windows
BậtKích hoạtWM_ACTIVATEOnKeyPressWM_CHAR
Trong một cái nhấp chuộtWM_LBUTTONDOWNOnKeyUpWM_KEYUP
Đang tạoWM_TẠOOnPaintWM_SƠN
OnDblClickWM_LBUTTONDBCLKOnResizeWM_SIZE
OnKeyDownWM_KEYDOWNHẹn giờWM_TIMER

Bạn không nên tạo trình xử lý tin nhắn nếu có sự kiện được xác định trước cho nó. Trong những trường hợp như vậy, việc sử dụng xử lý sự kiện là hợp lý vì nó có ít hạn chế hơn.

Phát triển một chương trình sẽ cung cấp giao diện để sử dụng lệnh truyền tin nhắn Win2000/XP tiêu chuẩn gửi qua mạng. Cho phép người dùng chỉ định địa chỉ người nhận, nội dung tin nhắn và số lượng tin nhắn sẽ gửi. Đồng thời cung cấp khả năng chặn nhận tin nhắn từ các máy tính khác.

Phát triển hình thức

Tạo một dự án Delphi mới. Thay đổi tiêu đề biểu mẫu (thuộc tính Caption) thành Net Sender. Đặt ba thành phần danh mục Nhãn chồng lên nhau dọc theo cạnh trái của biểu mẫu. Tiêu chuẩn và đặt thuộc tính Caption của chúng thành Địa chỉ IP:, Tin nhắn: và Số lượng:.

Đặt thành phần Chỉnh sửa danh mục bên cạnh mỗi nhãn Tiêu chuẩn. Đặt tên cho ip trên cùng (thuộc tính Tên) và gán giá trị cho thuộc tính Văn bản là 192.168.0.1.; đặt tên cho trường giữa là txt và gán thuộc tính Text cho một số văn bản tin nhắn mặc định; Đặt tên cho trường dưới cùng như thế nào và đặt thuộc tính Text thành 1.

Trong các thành phần được liệt kê, đặt thành phần Hộp kiểm danh mục Tiêu chuẩn. Đặt tên là an toàn, đặt thuộc tính Caption thành Tắt nhận tin nhắn và thuộc tính Đã kiểm tra thành True.

Ở cuối biểu mẫu, đặt một nút (thành phần danh mục Nút Tiêu chuẩn), đặt thuộc tính Caption của nó thành Send. Chúng ta cũng cần một bộ đếm thời gian (loại Bộ hẹn giờ thành phần Hệ thống), trong đó thuộc tính Interval phải được đặt thành 10.

Hình dạng kết quả phải tương ứng với hình. 15.1.

Cơm. 15.1. Mẫu chương trình gửi tin nhắn trên mạng cục bộ

Phát triển mã chương trình

Trước hết, hãy viết quy trình đánh bom của riêng chúng ta, quy trình này sẽ đọc tất cả cài đặt và gửi tin nhắn. Khai báo thủ tục này với tư cách là thành viên riêng của lớp biểu mẫu:

Chúng ta cũng cần một biến toàn cục i có kiểu số nguyên:

Bây giờ, hãy tạo một bản triển khai quy trình đặt bom trong phần triển khai:

thủ tục TForm1.bomb();
nếu như thế nào.Text= "" thì thế nào.Text:= "1";
nếu ip.Text = "" thì ip.Text:= "127.0.0.1";(nếu địa chỉ IP không được chỉ định thì chúng tôi sẽ gửi nó đến máy tính cục bộ)
WinExec(PChar("net send " + ip.Text + """ + txt.Text + """), 0);//gửi tin nhắn

Quy trình này kiểm tra xem tất cả các trường bắt buộc đã được điền hay chưa. Nếu không có nội dung tin nhắn thì đặt dấu "!" nếu địa chỉ IP không được chỉ định, thì chúng tôi sẽ gửi tin nhắn đến máy tính cục bộ có địa chỉ 127.0.0.1; nếu số lượng tin nhắn không được chỉ định thì chúng tôi sẽ gửi một tin nhắn. Tin nhắn được gửi bằng lệnh gửi mạng tiêu chuẩn, có cú pháp sau:

net gửi tin nhắn địa chỉ IP.

Bây giờ hãy xử lý sự kiện OnTimer:

h:HWND;// lưu trữ ID cửa sổ
nếu không an toàn. Đã kiểm tra rồi//nếu hộp kiểm không được chọn
Hẹn giờ1.Đã bật:= Sai;// vô hiệu hóa giám sát
nếu an toàn. Đã kiểm tra rồi//nếu hộp kiểm được chọn
//tìm cửa sổ tin nhắn
h:= FindWindow(nil, "Dịch vụ tin nhắn");//đóng tất cả các cửa sổ tìm thấy
nếu h<>

Nếu hộp kiểm Tắt nhận tin nhắn được chọn thì chúng tôi sẽ bắt đầu giám sát các cửa sổ có tiêu đề cho biết đây là tin nhắn và đóng tất cả các cửa sổ tìm thấy. Nếu hộp kiểm không được chọn, việc giám sát sẽ bị tắt.

Để có thể chuyển đổi giữa hai chế độ này, bạn cần tạo trình xử lý sự kiện safe.OnClick:

nếu an toàn. Đã kiểm tra rồi//nếu hộp kiểm được chọn...
Hẹn giờ1.Enabled:= Đúng;//...bật giám sát

Khi nhấn nút Gửi chúng ta sẽ đơn giản gọi quy trình đặt bom:

Để giúp cuộc sống của người dùng dễ dàng hơn, chúng tôi sẽ đảm bảo rằng tin nhắn cũng được gửi bằng cách nhấn phím trong bất kỳ trường nhập văn bản nào. Để thực hiện việc này, bạn cần tạo trình xử lý sự kiện OnKeyPress cho từng trường. Mã của trình xử lý này dành cho trường ip, sau đó có thể được gán cho các trường txt và way:

nếu chìa khóa= #13 rồi// nếu một phím được nhấn
bom;//gửi tin nhắn

Mã nguồn mô-đun đầy đủ

Mã hoàn chỉnh của mô-đun chương trình để gửi tin nhắn qua mạng cục bộ được trình bày trong Liệt kê 15.1.

Liệt kê 15.1. Mô-đun chương trình để gửi tin nhắn qua mạng cục bộ

Windows, Tin nhắn, SysUtils, Biến thể, Lớp, Đồ họa, Điều khiển, Biểu mẫu, Hộp thoại, StdCtrls, ExtCtrls;

thủ tục Hẹn giờ1Timer(Người gửi: TObject);
thủ tục safeClick(Người gửi: TObject);
thủ tục ipKeyPress(Người gửi: TObject; var Key: Char);
thủ tục txtKeyPress(Người gửi: TObject; var Key: Char);
thủ tục wayKeyPress(Người gửi: TObject; var Key: Char);
thủ tục Button1Click(Người gửi: TObject);


//kiểm tra xem tin nhắn văn bản có trống không
nếu txt.Text = "" thì txt.Text:= "!";
// nếu số lượng không được chỉ định thì chúng tôi sẽ gửi một tin nhắn
nếu thế nào.Text= "" thì thế nào.Text:= "1";
nếu ip.Text = "" thì ip.Text:= "127.0.0.1"; (nếu địa chỉ IP không được chỉ định thì chúng tôi sẽ gửi nó đến máy tính cục bộ)
// gửi số lượng tin nhắn được chỉ định
đối với i:=1 đến StrToInt(how.Text) thì làm
WinExec(PChar("net send " + ip.Text + """ + txt.Text + """), 0); //gửi tin nhắn

thủ tục TForm1.Timer1Timer(Người gửi: TObject);
h:HWND; // lưu trữ ID cửa sổ
nếu không an toàn. Đã chọn rồi // nếu hộp kiểm không được chọn
Hẹn giờ1.Đã bật:= Sai; // vô hiệu hóa giám sát
nếu an toàn. Đã chọn thì // nếu hộp kiểm được chọn
//tìm cửa sổ tin nhắn
h:= FindWindow(nil, "Dịch vụ tin nhắn"); //đóng tất cả các cửa sổ tìm thấy
nếu h<>0 rồi PostMessage(h, WM_QUIT, 0, 0);

thủ tục TForm1.secureClick(Người gửi: TObject);
nếu an toàn. Đã chọn thì // nếu hộp kiểm được chọn...
Hẹn giờ1.Enabled:= Đúng; //...bật giám sát

thủ tục TForm1.ipKeyPress(Người gửi: TObject; khóa var: Char);
nếu key = #13 thì // nếu phím được nhấn
bom; //gửi tin nhắn

thủ tục TForm1.Button1Click(Người gửi: TObject);

⊚ Tất cả các tệp dự án và tệp thực thi của chương trình được thảo luận đều nằm trên đĩa CD kèm theo sách trong thư mục Chương 15.

Gửi tin nhắn

Giống như Windows gửi tin nhắn đến các cửa sổ khác nhau, bản thân ứng dụng cũng có thể cần trao đổi tin nhắn giữa các cửa sổ và điều khiển của chính nó. Có một số cách để gửi tin nhắn: phương thức PerForm() (hoạt động độc lập với API Windows), cũng như các hàm API Win32 SendMessage() và PostMessage().

Phương thức PerForm() mà tất cả các lớp con của lớp TControl đều có:

function TControl.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;

Để gửi tin nhắn đến một biểu mẫu hoặc điều khiển, hãy sử dụng cú pháp sau:

RetVal:= ControlName.PerForm(MessageID, wParam, lParam);

Khi PerForm() được gọi, điều khiển sẽ không quay trở lại chương trình gọi cho đến khi tin nhắn được xử lý. Phương pháp này chuyển tin nhắn mà không cần thông qua hệ thống nhắn tin API của Windows.

Các hàm API SendMessage() và PostMessage() được khai báo trong mô-đun Windows như sau:

hàm SendMessage(hWnd: HWND; Msg: UINT; wParam: WPARAM;

lParam: LPARAM): LRESULT; stdcall;

hàm PostMessage(hWnd: HWND; Msg: UINT;

wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;

hWnd – tay cầm cửa sổ nhận tin nhắn; Msg – mã định danh tin nhắn; wParam và lParam – dữ liệu bổ sung.

Hàm SendMessage(), giống như phương thức PerForm(), gửi tin nhắn trực tiếp đến thủ tục cửa sổ và đợi nó được xử lý, trong khi hàm PostMessage() đặt tin nhắn vào hàng đợi tin nhắn và trả lại quyền điều khiển cho chương trình được gọi nó mà không cần đợi kết quả xử lý.

Hàm SendMessage() trả về giá trị thu được sau khi xử lý tin nhắn. Hàm PostMessage() - trả về giá trị cho biết tin nhắn có được đăng thành công lên hàng đợi tin nhắn hay không.

Tin nhắn của người dùng

Khi phát triển ứng dụng, có thể xảy ra tình huống trong đó ứng dụng cần gửi một tin nhắn đặc biệt đến chính nó hoặc tới ứng dụng khác để thực hiện một số hành động. Đối với các tin nhắn do người dùng tạo, Windows bảo lưu các giá trị từ WM_USER đến $7FFF.

Ví dụ về tin nhắn tùy chỉnh:

TestMsg = WM_USER + 100; // ID tin nhắn

TForm1 = lớp(TForm)

// phương thức xử lý tin nhắn:

thủ tục MyMessage(var Msg: TMessage); tin nhắn TestMsg;

thủ tục TForm1.MyMessage(var Msg: TMessage);

ShowMessage("Đang chạy tin nhắn TestMsg");

Msg.Result:= 1; // kết quả trả về

Ví dụ về việc gửi tin nhắn đến biểu mẫu:

nếu Form1.PerForm(TestMsg, 0, 0) = 1 thì

nếu SendMessage(Form1.Handle, TestMsg, 0, 0) = 1 thì

ShowMessage("Tin nhắn được xử lý thành công");

nếu PostMessage(Form1.Handle, TestMsg, 0, 0) thì

ShowMessage("Tin nhắn đã được đưa vào hàng đợi tin nhắn");

Sự kiện Delphi

Sự kiện là điều gì đó xảy ra khi một chương trình đang chạy. Theo quan điểm của ngôn ngữ Delphi, một sự kiện là một thuộc tính của kiểu thủ tục và giá trị của nó là một con trỏ tới một phương thức nào đó. Gán giá trị cho thuộc tính đó có nghĩa là chỉ định địa chỉ của phương thức sẽ được thực thi khi sự kiện xảy ra. Những phương thức như vậy được gọi là xử lý sự kiện.

Việc sử dụng sự kiện cho phép bạn thêm chức năng mới vào lớp hiện có mà không cần tạo lớp con.

Thuộc tính sự kiện cố gắng bắt đầu bằng từ "Bật" theo sau là tên sự kiện.

Mối quan hệ giữa tin nhắn và sự kiện

Delphi cung cấp một giao diện để tương tác với các thông báo Windows, ít nhất là một số trong số đó. Nhiều sự kiện thành phần VCL có liên quan trực tiếp đến các thông báo Windows thuộc loại WM_XXX.