21CTO导读:本文详细描述了编程中的消息机制,包括Windows和Java体系。
package message;
import java.util.Queue;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
/**
* 消息
* @author luoweifu
*/
class Message {
//消息类型
public static final int KEY_MSG = 1;
public static final int MOUSE_MSG = 2;
public static final int SYS_MSG = 3;
private Object source; //来源
private int type; //类型
private String info; //信息
public Message(Object source, int type, String info) {
super();
this.source = source;
this.type = type;
this.info = info;
}
public Object getSource() {
return source;
}
public void setSource(Object source) {
this.source = source;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public static int getKeyMsg() {
return KEY_MSG;
}
public static int getMouseMsg() {
return MOUSE_MSG;
}
public static int getSysMsg() {
return SYS_MSG;
}
}
interface MessageProcess {
public void doMessage(Message msg);
}
/**
* 窗口模拟类
*/
class WindowSimulator implements MessageProcess{
private ArrayBlockingQueue msgQueue;
public WindowSimulator(ArrayBlockingQueue msgQueue) {
this.msgQueue = msgQueue;
}
public void GenerateMsg() {
while(true) {
Scanner scanner = new Scanner(System.in);
int msgType = scanner.nextInt();
if(msgType < 0) { //输入负数结束循环
break;
}
String msgInfo = scanner.next();
Message msg = new Message(this, msgType, msgInfo);
try {
msgQueue.put(msg); //新消息加入到队尾
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
/**
* 消息处理
*/
public void doMessage(Message msg) {
switch(msg.getType()) {
case Message.KEY_MSG:
onKeyDown(msg);
break;
case Message.MOUSE_MSG:
onMouseDown(msg);
break;
default:
onSysEvent(msg);
}
}
//键盘事件
public static void onKeyDown(Message msg) {
System.out.println("键盘事件:");
System.out.println("type:" + msg.getType());
System.out.println("info:" + msg.getInfo());
}
//鼠标事件
public static void onMouseDown(Message msg) {
System.out.println("鼠标事件:");
System.out.println("type:" + msg.getType());
System.out.println("info:" + msg.getInfo());
}
//操作系统产生的消息
public static void onSysEvent(Message msg) {
System.out.println("系统事件:");
System.out.println("type:" + msg.getType());
System.out.println("info:" + msg.getInfo());
}
}
/**
* 消息模拟
* @author luoweifu
*/
public class MessageSimulator {
//消息队列
private static ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(100);
public static void main(String args) {
WindowSimulator generator = new WindowSimulator(messageQueue);
//产生消息
generator.GenerateMsg();
//消息循环
Message msg = null;
while((msg = messageQueue.poll()) != null) {
((MessageProcess) msg.getSource()).doMessage(msg);
}
}
}
#pragma onceWin32Test.cpp 代码如下:
#include <windows.h>
#include <atltypes.h>
#include <tchar.h>
//资源ID
#define ID_BUTTON_DRAW 1000
#define ID_BUTTON_SWEEP 1001
// 注册窗口类
ATOM AppRegisterClass(HINSTANCE hInstance);
// 初始化窗口
BOOL InitInstance(HINSTANCE, int);
// 消息处理函数(又叫窗口过程)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// (白色背景)按钮事件
void OnButtonWhite();
// (灰色背景)按钮事件
void OnButtonGray();
// 绘制事件
void OnDraw(HDC hdc);
#include "stdafx.h"
#include "Win32Test.h"
//字符数组长度
#define MAX_LOADSTRING 100
//全局变量
HINSTANCE hInst; // 当前实例
TCHAR g_szTitle[MAX_LOADSTRING] = TEXT("Message process"); // 窗口标题
TCHAR g_szWindowClass[MAX_LOADSTRING] = TEXT("AppTest"); // 窗口类的名称
HWND g_hWnd; // 窗口句柄
bool g_bWhite = false; // 是否为白色背景
//WinMain入口函数
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// 注册窗口类
if(!AppRegisterClass(hInstance))
{
return (FALSE);
}
// 初始化应用程序窗口
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
// 注册窗口类
ATOM AppRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = g_szWindowClass;
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
// 保存实例化句柄并创建主窗口
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 保存handle到全局变量
g_hWnd = CreateWindow(g_szWindowClass, g_szTitle, WS_OVERLAPPEDWINDOW, 0, 0, 400, 300, NULL, NULL, hInstance, NULL);
// 创建按钮
HWND hBtWhite = CreateWindowEx(0, L"Button", L"白色", WS_CHILD | WS_VISIBLE | BS_TEXT, 100, 100, 50, 20, g_hWnd, (HMENU)ID_BUTTON_DRAW, hInst, NULL);
HWND hBtGray = CreateWindowEx(0, L"Button", L"灰色", WS_CHILD | WS_VISIBLE | BS_CENTER, 250, 100, 50, 20, g_hWnd, (HMENU)ID_BUTTON_SWEEP, hInst, NULL);
if (!g_hWnd)
{
return FALSE;
}
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
return TRUE;
}
// (窗口)消息处理
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
//wmEvent = HIWORD(wParam);
switch (wmId)
{
case ID_BUTTON_DRAW:
OnButtonWhite();
break;
case ID_BUTTON_SWEEP:
OnButtonGray();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
OnDraw(hdc);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//事件处理
//按下hBtWhite时的事件
void OnButtonWhite()
{
g_bWhite = true;
InvalidateRect(g_hWnd, NULL, FALSE); //刷新窗口
}
//按下hBtGray时的事件
void OnButtonGray()
{
g_bWhite = false;
InvalidateRect(g_hWnd, NULL, FALSE); //刷新窗口
}
//绘制事件(每次刷新时重新绘制图像)
void OnDraw(HDC hdc)
{
POINT oldPoint;
SetViewportOrgEx(hdc, 0, 0, &oldPoint);
RECT rcView;
GetWindowRect(g_hWnd, &rcView); // 获得句柄的画布大小
HBRUSH hbrWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
HBRUSH hbrGray = (HBRUSH)GetStockObject(GRAY_BRUSH);
if (g_bWhite)
{
FillRect(hdc, &rcView, hbrWhite);
} else
{
FillRect(hdc, &rcView, hbrGray);
}
SetViewportOrgEx(hdc, oldPoint.x, oldPoint.y, NULL);
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)中的四个参数就是消息的相关信息(消息来自的句柄、消息类型等),函数中通过switch/case根据不同的消息类型分别进行不同的处理。在收到相应类型的消息之后,可调用相应的函数去处理,如OnButtonWhite、OnButtonGray、OnDraw,这就是事件处理的雏形。
typedef struct tagMsg消息主要有三种类型:
{
HWND hwnd; //接受该消息的窗口句柄
UINT message; //消息常量标识符,也就是我们通常所说的消息号
WPARAM wParam; //32位消息的特定附加信息,确切含义依赖于消息值
LPARAM lParam; //32位消息的特定附加信息,确切含义依赖于消息值
DWORD time; //消息创建时的时间
POINT pt; //消息创建时的鼠标/光标在屏幕坐标系中的位置
}MSG;
#define ID_BUTTON_TEST 10022.在OnButtonWhite中分别用SendMessage和PostMessage发送消息
void OnButtonWhite()3.在消息循环中增加ID_BUTTON_TEST的判断
{
g_bWhite = true;
InvalidateRect(g_hWnd, NULL, FALSE); //刷新窗口
SendMessage(g_hWnd, WM_COMMAND, ID_BUTTON_TEST, 0);
//PostMessage(g_hWnd, WM_COMMAND, ID_BUTTON_TEST, 0);
}
while (GetMessage(&msg, NULL, 0, 0))
{
if (LOWORD(msg.wParam) == ID_BUTTON_TEST)
{
OutputDebugString(L"This is a ID_BUTTON_TEST message."); // [BreakPoint1]
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
case ID_BUTTON_TEST:
{
OutputDebugString(L"This is a ID_BUTTON_TEST message."); // [BreakPoint2]
}
break;
case ID_BUTTON_DRAW:
OnButtonWhite();
break;
case ID_BUTTON_SWEEP:
OnButtonGray();
break;
import javax.swing.*;上面这个例子中,窗口和所有的控件创建完成之后,btEqual按钮邦定了一个监听对象additionCalculate,一旦这个按钮被点击,就会通知additionCalculate对象,additionCalculate对象监听到点击事件,就会调用actionPerformed方法作出相应的响应。additionCalculate是内部类AdditionCalculate的对象,AdditionCalculate实现了ActionListener 接口。
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: luoweifu
* Date: 15-5-5
* Time: 下午9:14
* To change this template use File | Settings | File Templates.
*/
public class Calculator {
/**
* 主窗口的宽度
*/
public static final int WIDTH = 500;
/**
* 主窗口的高度
*/
public static final int HEIGHT = 100;
private JFrame frameCalculator;
private JEditorPane editAddend1;
private JEditorPane editAddend2;
private JEditorPane editResult;
private JLabel labelPlus;
private JButton btEqual;
public Calculator() {
frameCalculator = new JFrame();
}
public void launchFrame() {
frameCalculator.setSize(WIDTH, HEIGHT);
frameCalculator.setLocationRelativeTo(null);
frameCalculator.setTitle("加法计算");
Container container = frameCalculator.getContentPane();
container.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
editAddend1 = new JEditorPane();
editAddend1.setBorder(new BevelBorder(BevelBorder.LOWERED));
editAddend2 = new JEditorPane();
editAddend2.setBorder(new BevelBorder(BevelBorder.LOWERED));
labelPlus = new JLabel("+");
btEqual = new JButton("=");
editResult = new JEditorPane();
editResult.setBorder(new BevelBorder(BevelBorder.LOWERED));
editResult.setEditable(false);
container.add(editAddend1);
container.add(labelPlus);
container.add(editAddend2);
container.add(btEqual);
container.add(editResult);
frameCalculator.setVisible(true);
//frameCalculator.setDefaultCloseOperation(EXIT_ON_CLOSE);
class AdditionCalculate implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int add1 = Integer.parseInt(editAddend1.getText());
int add2 = Integer.parseInt(editAddend2.getText());
int result = add1 + add2;
editResult.setText(result + "");
}
}
AdditionCalculate additionCalculate = new AdditionCalculate();
btEqual.addActionListener(additionCalculate);
}
public static void main(String args) {
Calculator calculator = new Calculator();
calculator.launchFrame();
}
}
//人,观察者结果如下:
class Person {
public void update(String data) {
System.out.println(data + "关电源...");
}
}
//水,被观察者
class Water {
private Person person;
private boolean isBoiled;
public Water() {
isBoiled = false;
}
public void SetBoiled() {
isBoiled = true;
notifyObserve();
}
public void addObserver(Person person) {
this.person = person;
}
public void removeObserver() {
if (person != null) {
person = null;
}
}
public void notifyObserve() {
if (isBoiled && person != null) {
person.update("水开了,");
isBoiled = false;
}
}
}
//客户端
public class ObserverModule {
public static void main(String args) {
Person person = new Person();
Water water = new Water();
water.addObserver(person);
water.SetBoiled();
}
}
水开了,关电源…
//观察者结果如下:
interface Observer {
public void update(Observable observable);
}
//被观察者
abstract class Observable {
protected boolean isChanaged;
protected List<Observer> observers = new ArrayList<Observer>();
public Observable() {
isChanaged = false;
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void removeObservers() {
observers.clear();
}
public void notifyObservers() {
if (isChanaged) {
for (int i = 0; i < observers.size(); i ++) {
observers.get(i).update(this);
}
isChanaged = false;
}
}
}
//人,温度监测
class TemperatureObserver implements Observer{
@Override
public void update(Observable observable) {
Water water = (Water)observable;
System.out.println("温度:" + water.getTemperature() + " 状态:" + water.getStatus());
System.out.println("TemperatureObserver observing...");
}
}
class BoildObserver implements Observer {
String doSomthing;
BoildObserver(String doSomthing) {
this.doSomthing = doSomthing;
}
@Override
public void update(Observable observable) {
Water water = (Water)observable;
if (water.getTemperature() >= 100) {
System.out.println("状态:" + water.getStatus());
System.out.println("BoildObserver:" + doSomthing);
}
}
}
//水,被观察者
class Water extends Observable{
private double temperature;
private String status;
public Water() {
super();
this.temperature = 0;
this.status = "冷水";
}
public Water(Observer observer) {
this();
observers.add(observer);
}
public double getTemperature() {
return temperature;
}
public String getStatus() {
return status;
}
public void change(double temperature) {
this.temperature = temperature;
if (temperature < 40) {
status = "冷水";
} else if (temperature >= 40 && temperature < 60) {
status = "温水";
}else if (temperature >= 60 && temperature < 100 ) {
status = "热水";
} else {
status = "开水";
}
this.isChanaged = true;
notifyObservers();
}
}
//客户端
public class ObserverModule {
public static void main(String args) {
TemperatureObserver temperatureObserver = new TemperatureObserver();
BoildObserver boildObserver1 = new BoildObserver("关闭电源...");
BoildObserver boildObserver2 = new BoildObserver("继续保湿...");
Water water = new Water(temperatureObserver);
water.addObserver(boildObserver1);
water.addObserver(boildObserver2);
water.change(45);
water.change(80);
water.change(100);
}
}
温度:45.0 状态:温水
TemperatureObserver observing…
温度:80.0 状态:热水
TemperatureObserver observing…
温度:100.0 状态:开水
TemperatureObserver observing…
状态:开水
BoildObserver:关闭电源…
状态:开水
BoildObserver:继续保湿…
package java.util;
public class Observable {
private boolean changed = false;
private Vector obs;
public Observable() {
obs = new Vector();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
[/i]
[i]package java.util;
public interface Observer {
void update(Observable o, Object arg);
}
[/i]
作者:luoweifu
来源:21CTO.COM
本文为 @ 21CTO 创作并授权 21CTO 发布,未经许可,请勿转载。
内容授权事宜请您联系 webmaster@21cto.com或关注 21CTO 公众号。
该文观点仅代表作者本人,21CTO 平台仅提供信息存储空间服务。