Callback 在Java和C语言中的实现

1. Java

 

Using interfaces to implement the equivalent of callback functions in Java

www.java world.com/java world/java tips/jw-java tip10.html


Developers conversant in the event-driven programming model of MS-Windows and the X Window System are accustomed to passing function pointers that are invoked (that is, "called back") when something happens. Java's object-oriented model does not currently support method pointers, and thus seems to preclude using this comfortable mechanism. But all is not lost!

Java's support of interfaces provides a mechanism by which we can get the equivalent of callbacks. The trick is to define a simple interface that declares the method we wish to be invoked.

For example, suppose we want to be notified when an event happens. We can define an interface:

public interface InterestingEvent
{
    // This is just a regular method so it can return something or
    // take arguments if you like.
    public void interestingEvent ();
}



This gives us a grip on any objects of classes that implement the interface. So, we need not concern ourselves with any other extraneous type information. This is much nicer than hacking trampoline C functions that use the data field of widgets to hold an object pointer when using C++ code with Motif.

The class that will signal the event needs to expect objects that implement the InterestingEvent interface and then invoke the interestingEvent() method as appropriate.

public class EventNotifier
{
    private InterestingEvent ie;
    private boolean somethingHappened;
    public EventNotifier (InterestingEvent event)
    {
    // Save the event object for later use.
    ie = event;
    // Nothing to report yet.
    somethingHappened = false;
    }
    //... 
    public void doWork ()
    {
    // Check the predicate, which is set elsewhere.
    if (somethingHappened)
        {
        // Signal the even by invoking the interface's method.
        ie.interestingEvent ();
        }
    //...
    }
    // ...
}



In that example, I used the somethingHappened predicate to track whether or not the event should be triggered. In many instances, the very fact that the method was called is enough to warrant signaling the interestingEvent().

The code that wishes to receive the event notification must implement the InterestingEvent interface and just pass a reference to itself to the event notifier.

public class CallMe implements InterestingEvent
{
    private EventNotifier en;
    public CallMe ()
    {
    // Create the event notifier and pass ourself to it.
    en = new EventNotifier (this);
    }
    // Define the actual handler for the event.
    public void interestingEvent ()
    {
    // Wow!  Something really interesting must have occurred!
    // Do something...
    }
    //...
}



That's all there is to it. I hope use this simple Java idiom will make your transition to Java a bit less jittery.

在 Windows 上,可以使用 Win32 API 的 GDI (Graphics Device Interface) 来实现放大输出字体的功能。具体来说,可以使用 `CreateFont` 函数来创建一个指定大小的字体对象,然后使用 `SelectObject` 函数将该字体对象选入输出设备上下文,从而实现输出放大字体的效果。 下面是一个简单的示例代码,演示如何使用 Win32 API 在窗口输出放大的字体: ```c #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { static TCHAR szAppName[] = TEXT("HelloWin"); HWND hwnd; MSG msg; WNDCLASS wndclass; // 注册窗口类 wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } // 创建窗口 hwnd = CreateWindow(szAppName, TEXT("Hello, Windows!"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 主消息循环 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HFONT hFont; static int cxChar, cyChar; switch (message) { case WM_CREATE: { // 创建字体对象 hFont = CreateFont(24, 12, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, TEXT("Arial")); // 获取字体大小 HDC hdc = GetDC(hwnd); TEXTMETRIC tm; GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmHeight; ReleaseDC(hwnd, hdc); } return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 选入字体对象 HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); // 输出放大后的文本 TCHAR szText[] = TEXT("Hello, Windows!"); TextOut(hdc, cxChar, cyChar, szText, lstrlen(szText)); // 恢复原来的字体对象 SelectObject(hdc, hOldFont); EndPaint(hwnd, &ps); } return 0; case WM_DESTROY: // 释放字体对象 DeleteObject(hFont); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } ``` 在这个示例代码,我们创建了一个 24 磅大小、Arial 字体的字体对象,并使用 `SelectObject` 函数选入该字体对象。然后,在窗口的绘制过程使用 `TextOut` 函数输出放大后的文本。 需要注意的是,这个示例代码只是一个简单的演示,实际应用可能需要更加复杂的处理逻辑,例如处理不同窗口大小、不同字体等情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值