一个利用FreeBasic编写的库,实现PowerBasic编程风格

一、前言:

本人由于是个老PowerBasic爱好者,随着64位系统变得越来越普及,32位的PB编程就显得越来越力不从心了。至此选择了FB作为转型的Basic语言,主要考虑是不但其支持32位及64位编程,更重要的是没有任何限制而且长期免费使用。

但是在使用的过程中,由于习惯了PB编程模式及界面,所以就萌生了个想法,在FB代码编辑中实现PB风格的代码编辑风格。

所以想到了就开始着手编写函数库(PBSTYLE.BI)。经过两天的尝试最终完成了PB编程代码风格的实现,并利用这个样式库,实现了第一个窗口程序,并成功转发系统消息。

二、FreeBasic下PB代码演示:

REM #COMPILE EXE
REM #DIM ALL
'------------------------------------------------------------------------------
'   ** Includes **
'------------------------------------------------------------------------------
REM #PBFORMS BEGIN INCLUDES 

#INCLUDE ONCE "PBStyle.bi"

REM #PBFORMS END INCLUDES
'------------------------------------------------------------------------------ 

REM #PBFORMS BEGIN CONSTANTS
#define IDD_DIALOG1   101
REM #PBFORMS END CONSTANTS

'------------------------------------------------------------------------------
'   ** Declarations **
'------------------------------------------------------------------------------ 
DECLARE FUNCTION ShowDIALOG1 ( BYVAL hParent AS HWND ) AS HWND
'DECLARE CALLBACK FUNCTION ShowDIALOG1Proc() 
GLOBAL CALL_ShowDIALOG1Proc AS WNDPROC = PROCPTR ( ShowDefWindowProc )
'==============================================================================
'   ** Main Application Entry Point **
'==============================================================================
FUNCTION PBMAIN (  ) AS LONG
    PBFormsInitComCtls ( ICC_WIN95_CLASSES OR ICC_DATE_CLASSES OR ICC_INTERNET_CLASSES )
    ShowDIALOG1 HWND_DESKTOP 
    FUNCTION = 1
END FUNCTION

'==============================================================================
'   ** CallBacks **
'==============================================================================
FUNCTION ShowDIALOG1Proc (  ) AS LRESULT
                                                 
    SELECT CASE CB.MSG  
      CASE WM_INITDIALOG
        SetWindowText( CB.HNDL, "系统消息 WM_INITDIALOG" )
        function = 1

      CASE WM_PAINT
        DIM Rct AS RECT
        DIM pnt AS PAINTSTRUCT
        DIM hDC AS HDC

        hDC = BeginPaint( CB.HNDL, @pnt )           
          GetClientRect ( CB.HNDL, @Rct )
          SetBkMode hDC, TRANSPARENT
          SetTextColor hDC, BGR ( 255, 0, 0 )
          DrawText ( hDC,  "Hello, World!", -1, @Rct, DT_SINGLELINE or DT_CENTER or DT_VCENTER )     
        EndPaint( CB.HNDL, @pnt )
        'SetWindowText( CB.HNDL, "系统消息 WM_PAINT" )
        FUNCTION = TRUE

      CASE WM_CLOSE
        IF MessageBox( CBHNDL, "是否退出程序?", "MTSERVER", MB_YESNOCANCEL ) = IDYES  THEN
           DIALOG_END CBHNDL
           EXIT FUNCTION
           ELSE 
              FUNCTION = 0 
        END IF
             
      CASE WM_DESTROY
        DIALOG_END CBHNDL
        EXIT FUNCTION
             
    END SELECT
     
END FUNCTION

'==============================================================================
'   ** Dialogs ** 
'==============================================================================
FUNCTION ShowDIALOG1 ( BYVAL hParent AS HWND ) AS HWND
REM #PBFORMS BEGIN DIALOG %IDD_DIALOG1->-> 
  DIM lRslt AS HWND = DIALOG_NEW ( hParent, "MainWClass", IDD_DIALOG1, "MT SERVER", 467, 361, _
                                   WS_OVERLAPPEDWINDOW, _
                                   WS_EX_DLGMODALFRAME OR WS_EX_CONTROLPARENT OR WS_EX_WINDOWEDGE )


REM #PBFORMS END DIALOG
  'AnimateWindow ( lRslt, 500, AW_HOR_POSITIVE )
  DIALOG_SHOW_MODAL lRslt, CALL_ShowDIALOG1Proc
     
REM #PBFORMS BEGIN CLEANUP %IDD_DIALOG1

REM #PBFORMS END CLEANUP
    
  FUNCTION = lRslt
END FUNCTION

运行效果图:

一个利用FreeBasic编写的库,实现PowerBasic编程风格_第1张图片

其中关键是模拟PB中CALLBAK FUNCTION回调消息CB结构,这个可以自己定义一个函数如SystemMessage ( hwnd, wMsg, wParam, lParam ),在窗体创建后将系统消息转为CB结构。

PB的CB结构体:

TYPE MESSAGE
    hWnd AS HWND
    Msg AS UINT
    wParam AS WPARAM
    lParam AS LPARAM
    TIME AS DWORD
    PT AS POINT
    lPrivate AS DWORD
    CTL AS UINT
    CTLMSG AS UINT
    HNDL AS HWND
    NMCODE AS UINT
    NMHDR AS ANY PTR
    NMHDRSTR AS WSTRING * 255
    NMHWND AS HWND
    NMID AS UINT
    VALUE AS UINT
END TYPE

在接收到不同的系统消息,赋予不同的值,窗口过程没有返回消息的话,则交给DefWindowProc处理。

举例如下形式:

GLOBAL CB AS MESSAGE
GLOBAL CBHNDL AS HWND
'-------------------------------------------------------------------------------
' 转发系统消息
'-------------------------------------------------------------------------------
SUB SystemMessage ( BYVAL hWnd AS HWND, _
                    BYVAL wMsg AS UINT, _
                    BYVAL wParam AS WPARAM, _
                    BYVAL lParam AS LPARAM ) 
    CB.hWnd   = hWnd                               
    CB.Msg    = wMsg
    CB.wParam = wParam
    CB.lParam = lParam

    IF wMsg = WM_CREATE OR wMsg = WM_NCCREATE THEN
        DIM pCreate AS CREATESTRUCT PTR
        pCreate = CPTR ( CREATESTRUCT PTR, lParam ) 
        CB.lParam = CAST ( LPARAM, pCreate )
    END IF
    
    IF wMsg = WM_COMMAND THEN
         CB.CTL = LOWORD ( wParam ) 
         CB.CTLMSG = HIWORD ( wParam )   
    END IF
    
    IF wMsg = WM_KEYDOWN THEN
         CB.VALUE = LOBYTE ( wParam )
    END IF    
 
    IF wMsg = WM_NOTIFY THEN
         DIM pNmh AS NMHDR PTR
         pNmh = CPTR ( NMHDR PTR, lParam ) 
         CB.NMHDR = pNmh
         CB.NMCODE = pNmh->code      
         CB.NMHWND = pNmh->hwndFrom
         CB.NMID = pNmh->idFrom
    END IF
    
    IF wMsg = WM_DRAWITEM THEN
         CB.CTL = wParam
         CB.NMHDR = CPTR ( DRAWITEMSTRUCT PTR, lParam )
    END IF
    
    CB.HNDL = CBHNDL
END SUB

另外在#lang "fb"语系下,FB不支持CALL内部指令,这个需要自己写个函数实现,如下:

TYPE FUNCPROC AS FUNCTION ( ) AS LRESULT '函数指针
'-------------------------------------------------------------------------------
' CALL回调函数
'-------------------------------------------------------------------------------
FUNCTION CALLBACK ( PRO as FUNCPROC ) as LRESULT
    dim lRet as LONG
    asm call [pro]   '过程函数入口地址
    asm mov [lRet], eax '取得过程返回值
    asm mov eax, eax
    FUNCTION = lRet
END FUNCTION  

全局变量GLOBAL可以使用宏定义:

#define GLOBAL  DIM SHARED 

局部变量LOCAL由于与内置函数冲突,需要改名:

#define LOCALL  STATIC

最后将新增的PB关键字添加到IDE目录下fbfull.lng的文件中即可。

三、总结:

由于水平问题难免思路及写作存在瑕疵,此文仅仅提供编程技巧作为探讨及对FB编程的应用。

你可能感兴趣的:(FreeBasic,PowerBasic编程,经验分享,windows,开发语言,青少年编程)