记录将C语言编写的Windows程序转换为python语言编写,演示具体效果在最后,这对初学者理解Windows消息机制及框架有一定参考作用

2023-12-13 08:34:32

主要思路 由于C语言的数组定义使用名字加中括号及括号内数字定义,但是在python中【】已经被作为列表 元组等序列类型分片、存取元素,因此我们不能像C语言那样定义数组

例如C语言? ? int? a[10]? 是声明定义一个含有10个int类型的数组a,而在执行语句部分,比如a[1]

表示使用索引号为1的元素 但是在python中 我们不需要声明语句 所以无法像C语言这样声明,于是我转换思路 我将其定义为类,那么声明中的数字就在类初始化中完成。在引用具体元素时,我想保持C语言风格 我使用字典来做类似C语言的引用,比如C语言中引用a[1]元素 我在python中使用a['1']来引用 使用字典方式,所以C语言的声明语句可以考虑使用python字典来初始化,元素引用使用字典形式,保证二者相似性,这样做的目的就是为了我转换C语言为python时候,尽量保持C语言的语法形式。同时注意,C语言中switch case结构在python中是match case 但是该语法似乎需要python3.10及以后的新版本才支持。我的是3.10所以运行测试通过

我初步定义一个二维数组版的python类

class pythonArrayD2():
    def __init__(self,rows,columns):
        assert isinstance(rows,int),"参数必须是正整数"
        assert isinstance(rows, int), "参数必须是正整数"
        self.rows=rows
        self.columns=columns
        self.Values={}
        self.Values=self.initValues()

    def initValues(self):
        for i in range(self.rows):
            for j in range(self.columns):
                self.Values[str(i)+','+str(j)]=0
        return self.Values

比如C语言定义一个二维数组? ?a[10][15]

使用我的类定义类似? ? ?a=pythonArrayD2(10,15)

而在引用元素时 比如 C语言? a[2][3]? ,在python中就为 a['2,3'] 使用字符串,并且用逗号分开。

基于此 我转换C语言程序为python就简单得多

为了区分 我在自己定义的文件名都加了数字1为后缀,其中一个定义Windows常量的文件,没有使用的原因主要给大家展示自己可以定义常量替换库文件中的常量 但是为了与C语言风格统一 我没有使用自己定义的常量 ,同时python中大家注意一件事 ,就是常量尽量定义在一个单独的文件中 然后使用全称引用,比如在const.py文件中定义常量 WM_SETFOCUS=7,我们在引用的时候使用全称

const.WM_SETFOCUS来引用,为什么要这样中 虽然C语言中可以直接使用WM_SETFOCUS来引用,那是因为编译性语言,在pyhong解释语言在 我们无法判断WM_SETFOCUS是常量还是变量,python通常解释为变量 容易变成局部变量受到回收机制影响 我给出C语言的Windows源码 和我自己转换后python代码 供初学者参考? 记住我们要研究编程者是如何思考的 ,而不是抄其代码,知道其思想后 我们可以随时使用任何语言编写程序 只是语法不同而已 但是思路不变 同时我们理解程序作用后 我们可以参考其代码增加更多功能为自己使用, 提到效率 ,当我们熟悉很多语言的语法后 就练习使用正则表达式转换任何语言 ,同时程序更为精炼,无须对大量常量或者固定语法变量手动转换,这就是编程的作用。下面分别给出python与C语言源码

该程序涉及几个文件??

1,主文件? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? main.py

2、定义C语言结构 Windows类型的文件? ??structure1.py

3、定义宏的文件? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?microDefine1.py

4、定义Windows常量的文件? 未用? ? ? ? ? ? ?win32con1.py

1. main.py

import sys

import structure1
from structure1 import *
import win32gui
import win32con
import ctypes
import ctypes.wintypes
from random import randint
from microDefine1 import *
from const1 import *
from win32con1 import *
import win32con1
debug=True
user32 = ctypes.windll.user32
gdi32=ctypes.windll.gdi32
#------全局变量----------------
className = 'MyWindowClass'
hwnd=0
msg = ctypes.wintypes.MSG()
wParam=None
lparam=None
idFocus=0  #由于python是解释型语言 所以在函数或者过程内使用全局变量要声明是全局变量 否则视为新建的局部变量
#可能你觉得不用在过程开头声明为全局变量也没事 但是因为程序不再时自上而下执行 但是有时希望更改全局变量值 而在另外过程中使用
szChildClass="checkChild"

szAppName="CheckWindwo"
hwndChild=structure1.pythonArrayD2(win32con1.DIVISIONS_CONST,win32con1.DIVISIONS_CONST)
def childWndproc(hwnd,msg,wParam,lParam):
   global idFocus
   #C语言结构类型在python中定义为类
   ps=structure1.PAINTSTRUCT()
   rect=structure1.RECT()
   hdc=0   #实际就是指针 但是python变量功能上相当于宏 变量类型自动检测 所以对应简单类型定义直接使用变量
   match msg:
       case win32con.WM_CREATE:
           #SetWindowLong第二个参数0对于子窗口有效 这里是子窗口的过程
           win32gui.SetWindowLong(hwnd,0,0)
           return 0
       case win32con.WM_KEYDOWN:
           #发生大多数消息给父窗口 自己只处理很少的消息
           if wParam!=win32con.VK_RETURN and wParam!=win32con.VK_SPACE:
               user32.SendMessageW(user32.GetParent(hwnd),msg,wParam,lParam)
               return 0
       case win32con.WM_LBUTTONDOWN:
           user32.SetWindowLongA(hwnd,0,1 ^ user32.GetWindowLongA(hwnd,0))
           user32.SetFocus(hwnd)
           user32.InvalidateRect(hwnd,win32con.NULL,False)
           return 0
           #作用就是窗口获得焦点后 发生一个重绘消息给窗口过程 那么就执行wm_paint消息下的代码
       case win32con.WM_SETFOCUS:
           idFocus=user32.GetWindowLongA(hwnd,win32con.GWL_ID)

       case win32con.WM_KILLFOCUS:
           user32.InvalidateRect(hwnd,win32con.NULL,True)
           return 0

       case win32con.WM_PAINT:
           hdc=user32.BeginPaint(hwnd,ctypes.byref(ps))
           user32.GetClientRect(hwnd,ctypes.byref(rect))
           gdi32.Rectangle(hdc,0,0,rect.right,rect.bottom)
           #再绘制X标记
           if user32.GetWindowLongA(hwnd,0):
               gdi32.MoveToEx(hdc,0,0,win32con.NULL)
               gdi32.LineTo(hdc,rect.right,rect.bottom,win32con.NULL)
               gdi32.MoveToEx(hdc,0,rect.bottom,win32con.NULL)
               gdi32.LineTo(hdc,rect.right,0)

           #绘制具有焦点时显示的虚线边框
           if hwnd==user32.GetFocus():
               #左坐标往前增加1/10
               rect.left +=rect.right//10
               rect.right -=rect.right//10
               rect.top +=rect.bottom//10
               rect.bottom -=rect.bottom//10

            #不填充区域
               gdi32.SelectObject(hdc,gdi32.GetStockObject(win32con.NULL_BRUSH))
               gdi32.SelectObject(hdc,gdi32.CreatePen(win32con.PS_DASH,0,0))
               gdi32.Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom)
               gdi32.DeleteObject(gdi32.SelectObject(hdc,gdi32.GetStockObject(win32con.BLACK_PEN)))

           user32.EndPaint(hwnd,ctypes.byref(ps))
           return 0
   return win32gui.DefWindowProc(hwnd,msg,wParam,lParam)



#----------------主窗口回调函数------------------------
def windowProc(hwnd, msg, wParam, lParam):
    # cxBlock = 0
    # cyBlock = 0
    # x = 0
    # y = 0
    global idFocus
    match msg:
        case win32con.WM_CREATE:
            print("第一时间收到创建消息")
            for x in range(win32con1.DIVISIONS_CONST):
                for y in range(win32con1.DIVISIONS_CONST):
                    hwndChild.Values[str(x) + "," + str(y)] = win32gui.CreateWindow(szChildClass, NULL,
                                                                            win32con.WS_CHILDWINDOW | win32con.WS_VISIBLE, 0, 0, 0, 0,
                                                                            hwnd, (y << 8) | x,
                                                                            user32.GetWindowLongA(hwnd, win32con.GWL_HINSTANCE),
                                                                            NULL)
                    # x += 1
                    # y += 1

            print("字典元素数量:",len(hwndChild.Values))

        case win32con.WM_SIZE:
            cxBlock = LOWORD(lParam) // win32con1.DIVISIONS_CONST
            cyBlock = HOWORD(lParam) // win32con1.DIVISIONS_CONST
            for x in range(win32con1.DIVISIONS_CONST):
                for y in range(win32con1.DIVISIONS_CONST):
                    user32.MoveWindow(hwndChild.Values[str(x) + "," + str(y)], x * cxBlock, y * cyBlock, cxBlock, cyBlock, True)

            return 0

        case win32con1.WM_LBUTTONDOWN:
            print("点击了鼠标左键")
            user32.MessageBeep(0)
            return 0
        case win32con1.WM_SETFOCUS:

            user32.SetFocus(user32.GetDlgItem(hwnd, idFocus))
            return 0
        case win32con.WM_KEYDOWN:

            x = idFocus & 0xff
            y = idFocus >> 8
            match wParam:
                case win32con.VK_UP:
                    y -= 1
                case win32con.VK_DOWN:
                    y += 1
                case win32con.VK_LEFT:
                    x -= 1
                case win32con.VK_RIGHT:
                    x += 1
                case win32con.VK_HOME:
                    x = y = 0
                case win32con.VK_END:
                    x = y = DIVISIONS_CONST - 1
                case _:
                    return 0
            x = (x + DIVISIONS_CONST) % DIVISIONS_CONST
            y = (y + DIVISIONS_CONST) % DIVISIONS_CONST
            idFocus = y << 8 | x
            user32.SetFocus(user32.GetDlgItem(hwnd, idFocus))
            return 0
        case win32con.WM_DESTROY:
            user32.PostQuitMessage(0)
            return 0
    return win32gui.DefWindowProc(hwnd, msg, wParam, lParam)


#定义主窗口类
def defineClass01(wndClass):
    #---------第一步   初始化类结构-python版本和C语言版本有一定的不同 某些域没有cbClsExtra-----------------------------------------
    #---------窗口类的作用就是定义窗口的一般性特征 或者通用特征

    wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW | win32con.CS_DBLCLKS  #每当窗口水平方向或垂直方向尺寸发生改变后 要完全刷新窗口
    wndClass.lpfnWndProc = windowProc                           #这个过程要处理基于这个窗口类创建的所有窗口的全部消息  使用函数名 实际引用提供指向函数的指针
    # wndClass.cbClsExtra=0
    wndClass.cbWndExtra = 0
    wndClass.hInstance = win32gui.GetModuleHandle(None)         #程序的实例句柄
    wndClass.hIcon=win32gui.LoadIcon(None,win32con.IDI_APPLICATION)
    wndClass.hCursor = win32gui.LoadCursor(None, win32con.IDC_ARROW)    #使用预定义图标 第一个参数为None  使用自定义图片 第一个参数为程序的实例句柄
    wndClass.hbrBackground =  win32con.COLOR_WINDOW     #win32gui.GetStockObject(win32con.WHITE_BRUSH) 或者获取图像对象#将窗口客户区边界设置为指定颜色
    wndClass.lpszClassName =szAppName
    return wndClass

def registerClass02(wndClass):
    #--------第二步  注册类---------------------------------------------
    wndClassAtom = win32gui.RegisterClass(wndClass)   #因为python中变量名就是结构体的地址 无须像C语言使用取地址运算符&

    if(wndClassAtom==0):
            print("注册失败")
            sys.exit(0)
def createWindow03(szAppName):
   hwnd = win32gui.CreateWindow(szAppName, "我的窗口", win32con.WS_OVERLAPPEDWINDOW | 0x00100000 |0x00200000,
                                 100, 100, 500, 500, None, None, win32gui.GetModuleHandle(None), None)
   return hwnd


#定义子窗口类
def registerChildClass02(ChildwndClass):
    ChildwndClass.lpfnWndProc=childWndproc
    ChildwndClass.cbWndExtra =ctypes.sizeof(ctypes.c_long)
    ChildwndClass.hIcon=0
    ChildwndClass.lpszClassName=szChildClass
    win32gui.RegisterClass(ChildwndClass)

def displayAndUpdateWindow04(hwnd):
    user32.ShowWindow(hwnd, win32con.SW_SHOW)  # 产生一个WM_SIZE消息
    user32.UpdateWindow(hwnd)  # 产生一个WM_PAINT消息

def createMessageStrunctAndSendIntInfo05(hwnd,msg,wParam,lparam):
#-------第五步 创建消息结构体并建立消息循环 -------------------------------
    user32.SendMessageA(hwnd,win32con.WM_CREATE,wParam,lparam)
    #发送按键消息 并且按键的虚拟码为0x01=VK_LBUTTON
    user32.SendMessageA(hwnd,win32con.WM_KEYDOWN,0X01,lparam)


def drawRectangle(hwnd):
    rect=RECT()
    user32.SetRect(ctypes.byref(rect),randint(1,500),randint(2,500),randint(1,500),randint(1,500))
    hBrush=gdi32.CreateSolidBrush(RGB(randint(0,255),randint(0,255),randint(0,255)))
    hdc=user32.GetDC(hwnd)
    user32.FillRect(hdc,ctypes.byref(rect),hBrush)
    user32.ReleaseDC(hwnd,hdc)
    gdi32.DeleteObject(hBrush)


def main():
    wndClass = win32gui.WNDCLASS()
    msg = ctypes.wintypes.MSG()
    wndClass=defineClass01(wndClass)
    registerClass02(wndClass)
    hwnd=createWindow03(szAppName)
    registerChildClass02(wndClass)
    displayAndUpdateWindow04(hwnd)
    createMessageStrunctAndSendIntInfo05(hwnd,msg,wParam,lparam)
    # def mainLoop(msg,):
    #第六步 自动执行消息队列  msg由操作系统自动生成 传递给你的程序


    while user32.GetMessageW(ctypes.byref(msg), None, wParam, lparam) != 0:
        #PeekMessageA在没有消息时返回0  有消息是返回非零
        if(user32.PeekMessageA(ctypes.byref(msg),None,wParam,lparam,win32con.PM_NOREMOVE)):
            print("检测自己应用程序收到消息", msg.message, "十六进制", hex(msg.message))
            match msg.message:
               case 0x83f1:
                    # match(wParam):
                    #     case win32con.VK_LBUTTON:
                    print("按下有窗口最大化最小化按钮的消息-- -----------")
               case 0x113:
                    print("收到定时器消息", msg.message, "十六进制", hex(msg.message))
            pass
        else:  #没有消息时处理
            # # print("heoll 这是空闲时间")
            # drawRectangle(hwnd)
            # # user32.UpdateWindow(hwnd)
            pass
        user32.TranslateMessage(ctypes.byref(msg))
        user32.DispatchMessageW(ctypes.byref(msg))


if __name__ == '__main__':
    main()

2.? ? structure1.py

import ctypes

HANDLE = ctypes.c_void_p

HDC = HANDLE

HWND=ctypes.c_void_p
LONG = ctypes.c_long
BOOL = ctypes.c_long
BYTE = ctypes.c_byte
WCHAR = ctypes.c_wchar
UINT = ctypes.c_uint
INT=ctypes.c_int
if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
    WPARAM = ctypes.c_ulong
    LPARAM = ctypes.c_long
elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
    WPARAM = ctypes.c_ulonglong
    LPARAM = ctypes.c_longlong

class RECT(ctypes.Structure):
    _fields_ = [("left", LONG),
                ("top", LONG),
                ("right", LONG),
                ("bottom", LONG)]
tagRECT = _RECTL = RECTL = RECT

class PAINTSTRUCT(ctypes.Structure):
    _fields_=[("hdc",HDC),
              ("fErase",BOOL),
              ("rcPaint",RECT),
              ("fRestore",BOOL),
              ("fIncUpdate",BOOL),
              ("rgbReserved",BYTE * 32)]
tagPAINTSTRUCT=PAINTSTRUCT

class TEXTMETRIC(ctypes.Structure):
  _fields_=[("tmHeight",LONG),
            ("tmAscent",LONG),
            ('tmDescent',LONG),
            ('tmInternalLeading', LONG),
            ('tmExternalLeading',LONG ),
            ('tmAveCharWidth',LONG ),
            ('tmMaxCharWidth',LONG ),
            ('tmWeight',LONG ),
            ('tmOverhang',LONG ),
            ('tmDigitizedAspectX',LONG ),
            ('tmDigitizedAspectY',LONG),
            ('tmFirstChar',WCHAR),
            ('tmLastChar',WCHAR),
            ('tmDefaultChar', WCHAR),
            ('tmBreakChar',WCHAR ),
            ('tmItalic',BYTE ),
            ('tmUnderlined',BYTE ),
            ('tmStruckOut', BYTE ),
            ('tmPitchAndFamily',BYTE),
            ('tmCharSet',BYTE)]
TEXTMETRICW=PTEXTMETRICW=NPTEXTMETRICW=LPTEXTMETRICW=TEXTMETRIC

class SCROLLINFO(ctypes.Structure):
    _fields_=[('cbSize',UINT),   #set to sizeof(SCROLLINFO)
              ('fMask',UINT),    #value to set or get
              ('nMin',INT),      #minimum range value
              ('nMax',INT),      #maximum range value
              ('nPage',UINT),    #page size
              ('nPos',INT),      #current position
              ('nTrackPos',INT)  #current track position
              ]
tagSCROLLINFO=PSCROLLINFO=SCROLLINFO

class WNDPROC(ctypes.Structure):
  _fields_=[("unnamedParam1",HWND),
            ("namedParam2",UINT),
            ("unnamedParam3",WPARAM),
            ("unnamedParam4",LPARAM)]

HINSTANCE=HANDLE
HICON=HANDLE
HCURSOR=HANDLE
HBRUSH=HANDLE
LPCWSTR=HANDLE
class WNDCLASS(ctypes.Structure):
    _fields_=[("style",UINT),
              ("lpfnWndProc",WNDPROC),
              ("cbClsExtra",ctypes.c_int),
              ("cbWndExtra",ctypes.c_int),
              ("hInstance",HINSTANCE),
              ("hIcon",HICON),
              ("hCursor",HCURSOR),
              ('hbrBackground',HBRUSH),
              ('lpszMenuName',LPCWSTR),
              ('lpszClassName',LPCWSTR)]

class POINT(ctypes.Structure):
    _fields_ = [("x", LONG),
                ("y", LONG)]


tagPOINT = _POINTL = POINTL = POINT

#演示 验证初始化后是否正确打印每个域的值
p=PAINTSTRUCT(1111,1)

COLORREF=ctypes.c_uint32
class LOGPEN(ctypes.Structure):
    _fields_=[('lopnStyle',UINT),
              ('lopnWidth',POINT),
              ('lopnColor',COLORREF)]
PLOGPEN=NPLOGPEN=LPLOGPEN=LOGPEN

print(p.hdc,p.fErase)
print(ctypes.sizeof(SCROLLINFO))

class pythonArrayD2():
    def __init__(self,rows,columns):
        assert isinstance(rows,int),"参数必须是正整数"
        assert isinstance(rows, int), "参数必须是正整数"
        self.rows=rows
        self.columns=columns
        self.Values={}
        self.Values=self.initValues()

    def initValues(self):
        for i in range(self.rows):
            for j in range(self.columns):
                self.Values[str(i)+','+str(j)]=0
        return self.Values

3.? ?microDefine1.py

def LOWORD(x):
    return x & 0xffff
def HOWORD(x):
    return (x>>16) & 0xffff
def MAX(a,b):
    if a>b:
        return a
    else:
        return b
def MIN(a,b):
    if a<b:
        return a
    else:
        return b
def RGB(red,green,blue):
    assert isinstance(red,(int,float)),"必须输入整数"
    assert isinstance(green, (int, float)), "必须输入整数"
    assert isinstance(green, (int, float)), "必须输入整数"
    red=int(red)
    green=int(green)
    blue=int(blue)
    if red>255:
       red=min(red,255)
    if red<0:
       red=max(0,red)
    if green>255:
       green=min(green,255)
    if green<0:
       green=max(0,green)
    if blue>255:
       blue=min(blue,255)
    if blue<0:
        blue=max(0,blue)
    return blue*(1<<16)+green*(1<<8)+red

4? 这个文件只是给出一种思路 ,可以不用 仅供参考? ?win32con1.py

DIVISIONS_CONST=5
WM_CREATE=1
DIVISIONS_CONST=5
NULL=None
WS_CHILDWINDOW=1073741824
WS_VISIBLE=268435456
GWL_HINSTANCE=-6
WM_SIZE=5
WM_LBUTTONDOWN=513
WM_SETFOCUS=7

以下是Windows源码? 世界著名技术作家Charles Petzold编写的 所以参考价值极高

/*-------------------------------------------------
? ?CHECKER4.C -- Mouse Hit-Test Demo Program No. 4
? ? ? ? ? ? ? ? ?(c) Charles Petzold, 1998
? -------------------------------------------------*/

#include <windows.h>

#define DIVISIONS 5

LRESULT CALLBACK WndProc ? (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ;

int ? idFocus = 0 ;
TCHAR szChildClass[] = TEXT ("Checker4_Child") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
? ? ? ? ? ? ? ? ? ? PSTR szCmdLine, int iCmdShow)
{
? ? ?static TCHAR szAppName[] = TEXT ("Checker4") ;
? ? ?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 ("Program requires Windows NT!"),?
? ? ? ? ? ? ? ? ? ? ? szAppName, MB_ICONERROR) ;
? ? ? ? ? return 0 ;
? ? ?}
? ? ?
? ? ?wndclass.lpfnWndProc ? = ChildWndProc ;
? ? ?wndclass.cbWndExtra ? ?= sizeof (long) ;
? ? ?wndclass.hIcon ? ? ? ? = NULL ;
? ? ?wndclass.lpszClassName = szChildClass ;
? ? ?
? ? ?RegisterClass (&wndclass) ;
? ? ?
? ? ?hwnd = CreateWindow (szAppName, TEXT ("Checker4 Mouse Hit-Test Demo"),
? ? ? ? ? ? ? ? ? ? ? ? ? WS_OVERLAPPEDWINDOW,
? ? ? ? ? ? ? ? ? ? ? ? ? CW_USEDEFAULT, CW_USEDEFAULT,
? ? ? ? ? ? ? ? ? ? ? ? ? CW_USEDEFAULT, CW_USEDEFAULT,
? ? ? ? ? ? ? ? ? ? ? ? ? NULL, NULL, hInstance, NULL) ;
? ? ?
? ? ?ShowWindow (hwnd, iCmdShow) ;
? ? ?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 HWND hwndChild[DIVISIONS][DIVISIONS] ;
? ? ?int ? ? ? ? cxBlock, cyBlock, x, y ;
? ? ?
? ? ?switch (message)
? ? ?{
? ? ?case WM_CREATE :
? ? ? ? ? for (x = 0 ; x < DIVISIONS ; x++)
? ? ? ? ? ? ? ?for (y = 0 ; y < DIVISIONS ; y++)
? ? ? ? ? ? ? ? ? ? hwndChild[x][y] = CreateWindow (szChildClass, NULL,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? WS_CHILDWINDOW | WS_VISIBLE,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0, 0, 0, 0,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? hwnd, (HMENU) (y << 8 | x),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NULL) ;
? ? ? ? ? return 0 ;
? ? ? ? ? ? ? ?
? ? ?case WM_SIZE :
? ? ? ? ? cxBlock = LOWORD (lParam) / DIVISIONS ;
? ? ? ? ? cyBlock = HIWORD (lParam) / DIVISIONS ;
? ? ? ? ??
? ? ? ? ? for (x = 0 ; x < DIVISIONS ; x++)
? ? ? ? ? ? ? ? for (y = 0 ; y < DIVISIONS ; y++)
? ? ? ? ? ? ? ? ? ? MoveWindow (hwndChild[x][y],
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? x * cxBlock, y * cyBlock,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cxBlock, cyBlock, TRUE) ;
? ? ? ? ? return 0 ;
? ? ? ? ? ? ? ? ? ? ? ?
? ? ?case WM_LBUTTONDOWN :
? ? ? ? ? MessageBeep (0) ;
? ? ? ? ? return 0 ;

? ? ? ? ? // On set-focus message, set focus to child window

? ? ?case WM_SETFOCUS:
? ? ? ? ? SetFocus (GetDlgItem (hwnd, idFocus)) ;
? ? ? ? ? return 0 ;

? ? ? ? ? // On key-down message, possibly change the focus window

? ? ?case WM_KEYDOWN:
? ? ? ? ? x = idFocus & 0xFF ;
? ? ? ? ? y = idFocus >> 8 ;

? ? ? ? ? switch (wParam)
? ? ? ? ? {
? ? ? ? ? case VK_UP: ? ?y-- ; ? ? ? ? ? ? ? ? ? ?break ;
? ? ? ? ? case VK_DOWN: ?y++ ; ? ? ? ? ? ? ? ? ? ?break ;
? ? ? ? ? case VK_LEFT: ?x-- ; ? ? ? ? ? ? ? ? ? ?break ;
? ? ? ? ? case VK_RIGHT: x++ ; ? ? ? ? ? ? ? ? ? ?break ;
? ? ? ? ? case VK_HOME: ?x = y = 0 ; ? ? ? ? ? ? ?break ;
? ? ? ? ? case VK_END: ? x = y = DIVISIONS - 1 ; ?break ;
? ? ? ? ? default: ? ? ? return 0 ;
? ? ? ? ? }

? ? ? ? ? x = (x + DIVISIONS) % DIVISIONS ;
? ? ? ? ? y = (y + DIVISIONS) % DIVISIONS ;

? ? ? ? ? idFocus = y << 8 | x ;

? ? ? ? ? SetFocus (GetDlgItem (hwnd, idFocus)) ;
? ? ? ? ? return 0 ;

? ? ?case WM_DESTROY :
? ? ? ? ? PostQuitMessage (0) ;
? ? ? ? ? return 0 ;
? ? ?}
? ? ?return DefWindowProc (hwnd, message, wParam, lParam) ;
}

LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?WPARAM wParam, LPARAM lParam)
{
? ? ?HDC ? ? ? ? hdc ;
? ? ?PAINTSTRUCT ps ;
? ? ?RECT ? ? ? ?rect ;
? ? ?
? ? ?switch (message)
? ? ?{
? ? ?case WM_CREATE :
? ? ? ? ? SetWindowLong (hwnd, 0, 0) ; ? ? ? // on/off flag
? ? ? ? ? return 0 ;

? ? ?case WM_KEYDOWN:
? ? ? ? ? ? ? ?// Send most key presses to the parent window
? ? ? ? ??
? ? ? ? ? if (wParam != VK_RETURN && wParam != VK_SPACE)
? ? ? ? ? {
? ? ? ? ? ? ? ?SendMessage (GetParent (hwnd), message, wParam, lParam) ;
? ? ? ? ? ? ? ?return 0 ;
? ? ? ? ? }
? ? ? ? ? ? ? ?// For Return and Space, fall through to toggle the square
? ? ? ? ??
? ? ?case WM_LBUTTONDOWN :
? ? ? ? ? SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
? ? ? ? ? SetFocus (hwnd) ;
? ? ? ? ? InvalidateRect (hwnd, NULL, FALSE) ;
? ? ? ? ? return 0 ;

? ? ? ? ? ? ? ?// For focus messages, invalidate the window for repaint
? ? ? ? ??
? ? ?case WM_SETFOCUS:
? ? ? ? ? idFocus = GetWindowLong (hwnd, GWL_ID) ;

? ? ? ? ? ? ? ?// Fall through

? ? ?case WM_KILLFOCUS:
? ? ? ? ? InvalidateRect (hwnd, NULL, TRUE) ;
? ? ? ? ? return 0 ;
? ? ? ? ??
? ? ?case WM_PAINT :
? ? ? ? ? hdc = BeginPaint (hwnd, &ps) ;
? ? ? ? ??
? ? ? ? ? GetClientRect (hwnd, &rect) ;
? ? ? ? ? Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;

? ? ? ? ? ? ? ?// Draw the "x" mark
? ? ? ? ??
? ? ? ? ? if (GetWindowLong (hwnd, 0))
? ? ? ? ? {
? ? ? ? ? ? ? ?MoveToEx (hdc, 0, ? ? ? ? ?0, NULL) ;
? ? ? ? ? ? ? ?LineTo ? (hdc, rect.right, rect.bottom) ;
? ? ? ? ? ? ? ?MoveToEx (hdc, 0, ? ? ? ? ?rect.bottom, NULL) ;
? ? ? ? ? ? ? ?LineTo ? (hdc, rect.right, 0) ;
? ? ? ? ? }

? ? ? ? ? ? ? ?// Draw the "focus" rectangle
? ? ? ? ??
? ? ? ? ? if (hwnd == GetFocus ())
? ? ? ? ? {
? ? ? ? ? ? ? ?rect.left ? += rect.right / 10 ;
? ? ? ? ? ? ? ?rect.right ?-= rect.left ;
? ? ? ? ? ? ? ?rect.top ? ?+= rect.bottom / 10 ;
? ? ? ? ? ? ? ?rect.bottom -= rect.top ;

? ? ? ? ? ? ? ?SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
? ? ? ? ? ? ? ?SelectObject (hdc, CreatePen (PS_DASH, 0, 0)) ;
? ? ? ? ? ? ? ?Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
? ? ? ? ? ? ? ?DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
? ? ? ? ? }

? ? ? ? ? EndPaint (hwnd, &ps) ;
? ? ? ? ? return 0 ;
? ? ?}
? ? ?return DefWindowProc (hwnd, message, wParam, lParam) ;
}
?

最后是python和C语言演示效果图

python?

c语言效果

文章来源:https://blog.csdn.net/pengg123h/article/details/134962502
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。