记录今日将C语言的Windows程序更改为python语言Windows程序,实现子窗口控制,类似微信程序框架最简单的原型

news2024/11/15 17:20:16

基本思路 为什么要选择python制作Windows应用程序,主要就是源代码直接展示,发现问题随时修改,同时可以不断增加新的功能方便。  由于C语言的Windows程序中结构类型在python中不能使用, 因此我们按照ctypes模块指导意见继承structure为类来创建使用,但是我也使用python中的命名元组方式来使用C语言的结构类型,所以对于同样的C语言结构类型我们可以自己解释为python不同的类型 ,只要自己使用时知道如何使用C语言结构的各个域字段就可以。同时C语言在switch case语句只有python3.10及以后版本支持对应的语句 match case  所以注意python版本,安装支持库pywin32, 我的在Windows10下测试运行通过,我会给出实际代码,最后显示运行效果图 供初学者参考。

例如  C语言的结构

typedef struct tagRECT

     { LONG left;

      LONG top;

     LONG right;

     LONG bottom; } RECT

在python中 我们定义为

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

我同样可以定义为命名元组 ,不过按官方建议最好按上面的定义。

但是我知道如何解释 所以我也涉及到元组定义,例如

ButtonTuple=collections.namedtuple("ButtonTuple","iStyle szText chinese")

该程序主要涉及几个文件,我通常文件命名后面加个数字1,其内容非常简单,以示区别,定义多个文件主要目的是让自己的程序看起来不太臃肿 。展示一种编程风格而已 一定要遵循这种原则、 以后自己的其他程序可以重复利用

1、主程序文件                                                                main.py

2、涉及C语言结构 Windows类型定义的文件                 structureType1.py

3、宏定义文件                                                                microDefine1.py

4、按钮类型常数文件                                                     ButtonTypeConst1.py

1、main.py  代码

import collections
import ButtonTypeConst1
from structureType1 import *
import ctypes
from micro1 import *
import win32con
import win32gui
import sys
user32=ctypes.windll.user32
gdi32=ctypes.windll.gdi32
clib=ctypes.cdll.msvcrt
printf=ctypes.windll.LoadLibrary("msvcrt.dll")
#给元组元素起名称 然后可以使用名称来引用数据
#我能创建一个以ButtonTuple为名称的元组 就如C语言的数据结构一样 给每个域起个有意义的名字 而我们不必
#关心数据的类型 自己在初始化的时候自己检查  增加编程的灵活性
ButtonTuple=collections.namedtuple("ButtonTuple","iStyle szText chinese")
buttonList=[]

buttonList.append(ButtonTuple(ButtonTypeConst1.BS_PUSHBUTTON,"pushButton","普通按钮"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_DEFPUSHBUTTON,"DEFPUSHBUTTON","下压按钮"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_CHECKBOX,"CHECKBOX","复选框"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_AUTOCHECKBOX,"AUTOCHECKBOX","自动复选框"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_RADIOBUTTON,"RADIOBUTTON","自动选项按钮"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_3STATE,"3STATE","三态按钮"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_AUTO3STATE,"AUTO3STATE","自动三态按钮"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_GROUPBOX,"GROUPBOX","分组框"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_AUTORADIOBUTTON,"AUTORADIOBUTTON","自动选项按钮"))
buttonList.append(ButtonTuple(ButtonTypeConst1.BS_OWNERDRAW,"OWNERDRAW","拥有者绘制按钮"))

NUM=len(buttonList)
szAppName="ButtonLock"
hwndButtons=[]   #C语言中数组  python对应列表
rect=RECT()
szTop="message         wParam           lParam                中文"
szUnd="_______         ______           ______               ______"
szFormat="%-16s%04X-%04X     %08X-%08x       %s "
szbuffer=ctypes.create_string_buffer(b"0", 150)
cxChar=0
cyChar=0
ps=PAINTSTRUCT()
msg = MSG()
hInstance=win32gui.GetModuleHandle(None)
def windowProc(hwnd, msg, wParam, lParam):
    # global hwndButton
    global cxChar
    global cyChar
    global NUM
    match msg:
        case win32con.WM_CREATE:   #相当于初始化
            cxChar=LOWORD(user32.GetDialogBaseUnits())
            cyChar=HIWORD(user32.GetDialogBaseUnits())
            for i in range(NUM):
                hwndButtons.append(win32gui.CreateWindow("button",  #预定义类名
                                                       buttonList[i].szText,  #按钮标题
                                                       win32con.WS_CHILD | win32con.WS_VISIBLE | buttonList[i].iStyle,  #按钮风格
                                                       cxChar,cyChar*(1+2*i), #按钮坐标
                                                       20*cxChar,7*cyChar//4, #按钮宽 高
                                                       hwnd,i,   #父窗口句柄 按钮ID
                                                       hInstance,None))  #实例句柄
            return 0
        case win32con.WM_SIZE:
            rect.left = 24 * cxChar
            rect.top = 2 *cyChar
            rect.right=LOWORD(lParam)
            rect.bottom=HIWORD(lParam)

            return 0
        case win32con.WM_PAINT:
            user32.InvalidateRect(hwnd,ctypes.byref(rect),True)
            hdc=user32.BeginPaint(hwnd,ctypes.byref(ps))
            gdi32.SelectObject(hdc,gdi32.GetStockObject(win32con.SYSTEM_FIXED_FONT))
            gdi32.SetBkMode(hdc,win32con.TRANSPARENT)

            gdi32.TextOutW(hdc,24*cxChar,cyChar,szTop,len(szTop))
            gdi32.TextOutW(hdc,12*cyChar,cyChar,szUnd,len(szUnd))

            user32.EndPaint(hwnd,ctypes.byref(ps))
            return 0
        case win32con.WM_DRAWITEM :
            pass
        case win32con.WM_COMMAND:
            user32.ScrollWindow(hwnd,0,-cyChar,ctypes.byref(rect),ctypes.byref(rect))
            hdc=user32.GetDC(hwnd)
            gdi32.SelectObject(hdc,gdi32.GetStockObject(win32con.SYSTEM_FIXED_FONT))
            #wparam高位字节为按钮风格
            index=LOWORD(wParam)
            print("按钮的索引",index)
            gdi32.TextOutW(hdc,24*cxChar,cyChar*(rect.bottom//cyChar-1),
                          szbuffer,user32.wsprintfW(szbuffer,szFormat,"WM_DRAWITEM" if msg==win32con.WM_DRAWITEM  else "WM_COMMAND",HIWORD(wParam),
                                                 LOWORD(wParam),HIWORD(lParam),LOWORD(lParam),buttonList[index].chinese))

            user32.ReleaseDC(hwnd,hdc)
            user32.ValidateRect(hwnd,ctypes.byref(rect))

        case win32con.WM_DESTROY:
            user32.PostQuitMessage(0)
            return 0
    return win32gui.DefWindowProc(hwnd,msg,wParam,lParam)


#---------第一步   初始化类结构-python版本和C语言版本有一定的不同 某些域没有cbClsExtra-----------------------------------------
#---------窗口类的作用就是定义窗口的一般性特征 或者通用特征
wndClass = win32gui.WNDCLASS()
wndClass.cbWndExtra=0
wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW | win32con.CS_DBLCLKS  #每当窗口水平方向或垂直方向尺寸发生改变后 要完全刷新窗口
wndClass.lpfnWndProc = windowProc                           #这个过程要处理基于这个窗口类创建的所有窗口的全部消息  使用函数名 实际引用提供指向函数的指针
wndClass.hInstance = win32gui.GetModuleHandle(None)         #程序的实例句柄
wndClass.hCursor = win32gui.LoadCursor(None, win32con.IDC_ARROW)    #使用预定义图标 第一个参数为None  使用自定义图片 第一个参数为程序的实例句柄
wndClass.hbrBackground =  win32con.COLOR_WINDOW     #win32gui.GetStockObject(win32con.WHITE_BRUSH) 或者获取图像对象#将窗口客户区边界设置为指定颜色
wndClass.lpszClassName = szAppName

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

if(wndClassAtom==0):
        print("注册失败")
        sys.exit(0)
# print("注册结果",wndClassAtom)
#-------第三步  创建程序主窗口-------------------------------------------------
#窗口具有垂直和水平滚动条win32con.WS_HSCROLL=0x00100000  in32con.WS_VSCROLL=0x00200000L
hwnd = win32gui.CreateWindow(szAppName, "我的窗口buttonlock", win32con.WS_OVERLAPPEDWINDOW | 0x00100000 |0x00200000,
                             100, 100, 500, 500, None, None, win32gui.GetModuleHandle(None), None)

#---------第四步 显示并更新窗口
user32.ShowWindow(hwnd, win32con.SW_SHOW) #产生一个WM_SIZE消息
user32.UpdateWindow(hwnd)  #产生一个WM_PAINT消息


#-------第五步 创建消息结构体并建立消息循环 -------------------------------
# msg = ctypes.wintypes.MSG()

wParam=None
lparam=None
#手动调用一次回调函数 python调试时中不自动执行创建初始化
# windowProc(hwnd,win32con.WM_CREATE,0,0)

#-------自己使用函数调用---------------------------
user32.SendMessageA(hwnd,win32con.WM_CREATE,wParam)
hdc=user32.GetDC(hwnd)
testString="测试文字\n又是一个"
#注意 参数涉及字符串的函数可能都有ASCII版本和Unicode版本
gdi32.TextOutW(hdc,0,0,testString,len(testString))

user32.ReleaseDC(hwnd,hdc)

#第六步 自动执行消息队列  msg由操作系统自动生成 传递给你的程序
while user32.GetMessageW(ctypes.byref(msg), None, wParam, lparam) != 0:
    user32.TranslateMessage(ctypes.byref(msg))
    user32.DispatchMessageW(ctypes.byref(msg))



2、 structureType1.py  代码
import ctypes

HANDLE = ctypes.c_void_p

HDC = HANDLE
DWORD = ctypes.c_ulong
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)


class MSG(ctypes.Structure):
    _fields_ = [("hWnd", HWND),
                ("message", UINT),
                ("wParam", WPARAM),
                ("lParam", LPARAM),
                ("time", DWORD),
                ("pt", POINT)]
tagMSG = MSG

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 HIWORD(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、ButtonTypeConst1.py    代码

BS_PUSHBUTTON=0
BS_DEFPUSHBUTTON=1
BS_CHECKBOX=2
BS_AUTOCHECKBOX=3
BS_RADIOBUTTON=4
BS_3STATE=5
BS_AUTO3STATE=6
BS_GROUPBOX=7
BS_AUTORADIOBUTTON=8
BS_OWNERDRAW=9

运行效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1311435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务技术 RabbitMQ SpringAMQP P61-P76

B站学习视频https://www.bilibili.com/video/BV1LQ4y127n4?p61&vd_source8665d6da33d4e2277ca40f03210fe53a 文档资料: 链接&#xff1a;https://pan.baidu.com/s/1P_Ag1BYiPaF52EI19A0YRw?pwdd03r 提取码&#xff1a;d03r 一 初始MQ 1. 同步通讯 2. 异步通讯 3. MQ常…

低代码与自动化:加速软件开发的新趋势

低代码与自动化技术正在逐渐改变软件开发的面貌。随着科技的不断发展&#xff0c;传统的编程方式已经不再是唯一的选择。低代码和自动化技术正在为开发者提供更高效、更灵活的开发环境&#xff0c;使得软件开发变得更加简单、快速和高效。 低代码和自动化技术正在逐渐改变软件开…

理解JSX:提高前端开发效率的关键(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

百度搜索展现服务重构:进步与优化

作者 | 瞭东 导读 本文将简单介绍搜索展现服务发展过程&#xff0c;以及当前其面临的三大挑战&#xff1a;研发难度高、架构能力欠缺、可复用性低&#xff0c;最后提出核心解决思路和具体落地方案&#xff0c;期望大家能有所收货和借鉴。 全文4736字&#xff0c;预计阅读时间12…

高级C#技术(二)

前言 本章为高级C#技术的第二节也是最后一节。前一节在下面这个链接 高级C#技术https://blog.csdn.net/qq_71897293/article/details/134930989?spm1001.2014.3001.5501 匿名类型 匿名类型如其名&#xff0c;匿名的没有指定变量的具体类型。 举个例子&#xff1a; 1 创建…

MySQL数据库,视图、存储过程与存储函数

数据库对象&#xff1a; 常见的数据库对象&#xff1a; 视图&#xff1a; 视图是一种虚拟表&#xff0c;本身是不具有数据的占用很少的内存空间。 视图建立在已有表的基础上&#xff0c;视图赖以建立的这些表称为基表。 视图的创建和删除只影响视图本身&#xff0c;不影响对…

案例058:基于微信小程序的智能社区服务管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

计算机设计大赛信息可视化设计的获奖经验剖析解读—基于本专栏文章助力4C大赛【全网最全万字攻略-获奖必读】

文章目录 一.中国大学生计算机设计大赛1.1赛道解读1.2 信息可视化设计小类介绍1.2 小类区别解读 二.信息可视化设计赛道获奖经验2.1 四小类作品预览2.1.1 数据可视化小类-优秀参赛作品展览2.1.2 信息图形设计小类-优秀参赛作品展览2.1.3 动态信息影像&#xff08;MG动画&#x…

2024免费mac苹果电脑系统电脑管家CleanMyMac X

macOS已经成为最受欢迎的桌面操作系统之一&#xff0c;它提供了直观、简洁的用户界面&#xff0c;使用户可以轻松使用和管理系统。macOS拥有丰富的应用程序生态系统&#xff1b;还可以与其他苹果产品和服务紧密协作&#xff0c;如iPhone、iPad&#xff0c;用户可以通过iCloud同…

理解JSX:提高前端开发效率的关键(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

spring 笔记五 SpringMVC的数据响应

文章目录 SpringMVC的数据响应SpringMVC的数据响应方式回写数据 SpringMVC的数据响应 SpringMVC的数据响应方式 页面跳转 直接返回字符串通过ModelAndView对象返回 回写数据 直接返回字符串返回对象或集合 返回字符串形式 直接返回字符串&#xff1a;此种方式会将返回的字符…

nodejs+vue+微信小程序+python+PHP血液中心管理平台的设计与实现-计算机毕业设计推荐

实现采血的完整功能&#xff0c;系统用户主要分为两类&#xff0c;一类是管理员&#xff0c;一类是采血工作人员。管理员主要对采血工作人员以及血库进行管理。派发账号给员工作为采血工作人员&#xff0c;对血库的出库入库进行信息化管理。采血工作人员主要完成采血工作。通过…

jmeter,通过Ant插件生成html报告,展示接口详细信息

一、下载Ant 下载地址&#xff1a;Apache Ant - 二进制发行版 二、安装 1、Ant环境变量 解压Ant目录&#xff1b;配置系统环境变量&#xff0c;添加ANT_PATH&#xff0c;值为D:\Software\Ant_plugIn\apache-ant-1.10.14配置系统环境变量Path&#xff0c;添加Ant路径 %ANT_H…

MyBatisPlus基础入门笔记

MyBatisPlus基础入门笔记&#xff0c;源码可见下载链接 大家阅读时可善用目录功能&#xff0c;可以提高大家的阅读效率 下载地址&#xff1a;MyBatisPlus源码笔记 初识MyBatisPlus 入门案例 SpringBoot整合MyBatis&#xff08;复习&#xff09; 创建SpringBoot工程勾选使用的…

设计模式——适配器模式(结构型)

引言 适配器模式是一种结构型设计模式&#xff0c; 它能使接口不兼容的对象能够相互合作。 问题 假如你正在开发一款股票市场监测程序&#xff0c; 它会从不同来源下载 XML 格式的股票数据&#xff0c; 然后向用户呈现出美观的图表。 在开发过程中&#xff0c; 你决定在程序…

使用qt实现四则运算计算机项目

这是我们要包含的头文件 #include <QWidget> #include<QStack> #include<string.h> #include<string> 这是我在ui界面创建的计算机基础框架。 接下来要实现按住每个按钮在白框内显示&#xff1b; 因此我们要定义一个QString 类型的变量 QString e…

nginx服务前端访问查看无响应的问题

问题 nginx 启动之后&#xff0c;前端访问无数据&#xff0c;F12 查看&#xff0c;提示挂起。 以为是配置问题&#xff0c;查看配置文件&#xff0c;未发现配置的有问题。 原因 通过查看配置文件&#xff0c;发现转发的服务地址为127.0.0.1&#xff0c;手动ping 127.0.0.1&a…

AI人工智能与云原生:创新科技的完美结合

人工智能&#xff08;AI&#xff09;是当今科技领域的热门话题&#xff0c;而云原生则是一种新兴的软件开发和部署模式。AI人工智能与云原生的结合&#xff0c;为现代技术创新提供了无限的可能性。本文将探讨AI与云原生的关系&#xff0c;并介绍其如何在实际应用中实现协同效应…

谷歌宣布向云计算客户开放 Gemini Pro,开发者可用其构建应用

12 月 14 日消息&#xff0c;美国时间周三&#xff0c;谷歌宣布了一系列升级的人工智能&#xff08;AI&#xff09;功能&#xff0c;旨在为其云计算客户提供更好的服务。这家科技巨头正试图赶上竞争对手&#xff0c;比如微软和 OpenAI&#xff0c;它们都在积极利用人工智能的热…

docker安装最新版SQL Server并还原备份的数据库

docker安装数据库 拉取微软官方最新版镜像 docker pull mcr.microsoft.com/mssql/server 拉去镜像并创建容器 docker run -e "ACCEPT_EULAY" -e "SA_PASSWORDsa_password_123456" -p 1433:1433 -v /opt/:/opt --name sqlserver -d mcr.microsoft.com/ms…