windows.h系统函数
转载:https://blog.csdn.net/u010756046/article/details/82432312
// Windows系统函数.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <time.h>
#include <tlhelp32.h>
using namespace std;
//SendMessage(hWnd,WM_CHAR,WPARAM('g'),0);//发送一个字符(按键)消息g给当前鼠标所指向的窗口句柄
//参数 窗口句柄,WM_CHAR,要按下的键,0
//SendMessage(wnd,WM_RBUTTONDOWN,0,0);//鼠标右键按下,第三,四个参数说明了鼠标按下时的位置
//鼠标右键按下的消息类型是“WM_RBUTTONDOWN”,右键松开的消息是“WM_RBUTTONUP”
//获取随机数 len随机数范围 [0,len)
void random(const int len) {
    //头文件time.h 包含time clock函数
    //time获取1970年到现在的秒数
    //clock获取毫秒
    srand(time(0)+clock());//设置随机数种子
    while (1) {
        srand(time(0) + clock());//设置随机数种子
        int r = rand() % len;
        //cout << r << endl;
        if (r == 0 || r == len-1)cout << r << endl;
    }
}
//获取光标(Cursor)位置 根据光标位置获取窗口句柄
void fun1() {
    while (1) {
        POINT p;//POINT 点 结构体
        GetCursorPos(&p);//获取 光标 Pos点(传入 点内存地址)
        HWND hwnd = WindowFromPoint(p);//窗口 来自 点(传入 结构体点)--返回值 HWND 窗口句柄
        cout <<"鼠标位置X:"<<p.x<<" Y:"<<p.y<<"\n窗口句柄"<< hwnd <<endl;
        Sleep(100);
    }
}
//移动窗口 改变窗口大小 是否重绘
void fun2() {
    HWND hwnd = FindWindowA("Notepad","无标题 - 记事本");
    //窗口句柄 x y w h 是否重绘
    bool b=MoveWindow(hwnd,1000,500,900,500,0);
    cout << "返回值" << b << endl;
}
//设置窗口显示状态,如隐藏,最大化,最小化
void fun3() {
    HWND hwnd = FindWindowA("Notepad", "无标题 - 记事本");
    ShowWindow(hwnd, SW_SHOWNORMAL);
    //SW_HIDE:隐藏窗口并激活其他窗口。并激活其他窗口?当隐藏用
    //SW_MAXIMIZE:最大化指定的窗口。
    //SW_MINIMIZE:最小化指定的窗口并且激活在Z序中的下一个顶层窗口。
    //SW_RESTORE:激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志。
    //SW_SHOW:在窗口原来的位置以原来的尺寸激活和显示窗口。
    //SW_SHOWNORMAL 正常显示
}
//设置鼠标的位置、把鼠标移动到指定的位置
void fun4() {
    SetCursorPos(1042, 93);
    //srand(123);//设置随机数种子
    srand(time(0));//获取系统时间 设置随机数种子
    cout << rand() << endl;
    cout << rand() << endl;
    cout << rand() << endl;
    cout << rand() << endl;
    cout << rand() << endl;
}
//获得窗口大小
void fun5() {
    HWND hwnd = FindWindowA("Notepad", "无标题 - 记事本");
    RECT rect;//矩形 结构体
    //获取 客户端 矩形,参数1 窗口句柄,参数2 矩形指针,返回值 BOOL
    bool b1 = GetClientRect(hwnd, &rect);
    cout << "GetClientRect返回值" << b1 << endl;
    cout << "left:" << rect.left << endl; //0
    cout << "top:" << rect.top << endl; //0
    cout << "right:" << rect.right << endl;
    cout << "bottom:" << rect.bottom << endl;
    //因为与位置无关 所以left=0 top=0,right窗口宽度 bottom高度
    //注意:right bottom 为窗口实际的宽高
cout << endl;
//相对屏幕
    bool b2 = GetWindowRect(hwnd, &rect);
    cout << "GetWindowRect返回值" << b2 << endl;
    cout << "left:" << rect.left << endl;
    cout << "top:" << rect.top << endl;
    cout << "right:" << rect.right << endl;
    cout << "bottom:" << rect.bottom << endl;
    //right-left=宽度
    //bottom-top=高度
    cout << "width:" << rect.right - rect.left << endl;
    cout << "height:" << rect.bottom - rect.top << endl;
    //注意:width height 不是窗口实际的宽高(QQ截图用的就是这个函数,和QQ截图里计算的结果一样)
}
//运行一个程序
void fun6() {
    //运行的程序启动路径为当前程序的启动路径
//第一个参数hwnd是父窗口的句柄,可以为NULL
    //第二个参数lpOperation表示行为
    //第三个参数lpFile是程序的路径名
    //第四个参数lpParameters是给所打开程序的参数,可以为NULL
    //第五个参数lpDirectory可以为NULL
    //第六个参数nShowCmd跟ShowWindow函数的第二个参数一样,作用也一样,如果打开的程序有窗口的话,这个参数就指明了窗口如何显示SW_SHOWNORMAL(正常显示)
//字符集:
    //字符集"open"使用的是ascii
    //L"open"使用的是unicode,L"open" 相当于 _T("open")
//HWND hwnd = FindWindowA("Notepad", "无标题 - 记事本");
    //ShellExecute(hwnd, L"open", _T("NOTEPAD.exe"), NULL, NULL, SW_SHOWNORMAL);
    //ShellExecute(0, L"open", _T("NOTEPAD.exe"), NULL, NULL, SW_SHOWNORMAL);
    //ShellExecute(0, L"open", _T("NOTEPAD.exe"), L"C:\\Users\\Liziguo\\Desktop\\新建文本文档.txt", NULL, SW_SHOWNORMAL);//传参 打开桌面的记事本
    //ShellExecute(0, L"open", _T("java"), L"-jar C:\\Users\\Liziguo\\Desktop\\windows.h.jar", NULL, SW_SHOWNORMAL);//传参
    //ShellExecute(0,L"open",L"http://www.liziguo.cn",0,0,SW_SHOWNORMAL);//打开一个网址
    //ShellExecute(0,L"open",L"C:",0,0,SW_SHOWNORMAL);//打开C盘
    //ShellExecute(NULL, L"open", L"g:\\瓦力高清2.jpg", NULL, NULL, SW_SHOWNORMAL);//还可以根据文件后缀名选择相应的程序打开一个文件
//类似的函数还有WinExec,只有两个参数, 它的最后一个参数跟ShellExecute函数的最后一个参数一样
    //WinExec("NOTEPAD.EXE", SW_SHOWNORMAL);
    //WinExec("java -jar C:\\Users\\Liziguo\\Desktop\\windows.h.jar", SW_SHOWNORMAL);//传参
}
//GetModuleFileName根据模块导入表获取程序的完整路径
//CreateWindow创建窗口 跳过
//GetDC根据窗口句柄获取设备上下文。得到了一个窗口的设备上下文,就可以进行画图操作了,像画圆,画正方形,显示图片等函数都是要设备上下文(DC)句柄做参数的。
void fun7() {
    HWND hwnd = FindWindowA("Notepad", "无标题 - 记事本");
    HDC dc = GetDC(0);//获取这个窗口的设备上下文
    while (1) {
        //在窗口里画矩形(窗口被刷新时消失)
        Rectangle(dc, 20, 20, 120, 120);//left top right bottom
        Sleep(50);
    }
}
//在光标指向的窗口画图
void fun8() {
    POINT p;
    while (1) {
        GetCursorPos(&p);
        HWND hwnd = WindowFromPoint(p);
        HDC hdc = GetDC(hwnd);
        Rectangle(hdc, 20, 20, 120, 120);
        Sleep(50);
    }
}
//30.CreateToolhelp32Snapshot给当前进程拍一个照
//Process32First根据CreateToolhelp32Snapshot函数返回的句柄获取进程信息
//TerminateProcess结束一个进程
void fun9() {
    HWND hwnd = FindWindowA("Notepad", "无标题 - 记事本");
    DWORD id;
    GetWindowThreadProcessId(hwnd, &id);
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, false, id);
    TerminateProcess(handle, 0);//第一个是进程句柄,第二个填0就行了
}
//CreatePen创建一个画笔(返回画笔句柄)CreateSolidBrush创建一个画刷。相当于fun8()设置了 画笔和画刷
void fun10() {
    //函数定义:BOOL CreatePen(int nPenStyle, int nWidth, COLORREFcrColor);
//第一个参数,表示是什么类型的线,取值有以下:
    //PS_SOLID 画笔画出的是实线 PS_DASH 画笔画出的是虚线(nWidth必须是1) PS_DOT 画笔画出的是点线(nWidth必须是1)
    //PS_DASHDOT 画笔画出的是点划线(nWidth必须是1) PS_DASHDOTDOT 画笔画出的是点 - 点 - 划线(nWidth必须是1)
    //第二个参数是画笔的宽度,第三个参数是画笔的颜色,COLORREF类型可以RGB来获得如RGB(233, 128, 88); 分别是红绿蓝。
//如创建一个画笔:HPEN pen = CreatePen(PS_SOLID, 3, RGB(255, 78, 99));
//----------------------------------------------------------------------------------------------------------
    //CreateSolidBrush创建一个画刷
//只有一个COLORREF类型的参数
//HBRUSH brush = CreateSolidBrush(RGB(22, 182, 111));
    POINT p;
    HPEN hpen = CreatePen(PS_DOT, 1, RGB(7, 47, 231));
    HBRUSH hbrush = CreateSolidBrush(RGB(220, 220, 12));
    while (1) {
        GetCursorPos(&p);
        HWND hwnd = WindowFromPoint(p);
        HDC hdc = GetDC(hwnd);
        SelectObject(hdc, hpen);//选入画笔
        SelectObject(hdc, hbrush);//选入画刷
Rectangle(hdc, 20, 20, 120, 120);
        Sleep(1);
    }
}
//获取系统进程快照 获取系统所有进程
void fun11() {
    /*
    进程信息结构体:
        typedef struct tagPROCESSENTRY32 {
        DWORD dwSize;//结构大小
        DWORD cntUsage;//此进程的引用计数
        DWORD th32ProcessID;//进程ID
        DWORD th32DefaultHeapID;//进程默认堆ID
        DWORD th32ModuleID;//进程模块ID
        DWORD cntThreads;//此进程开启的线程计数
        DWORD th32ParentProcessID;//父进程ID
        LONG pcPriClassBase;//线程优先权
        DWORD dwFlags;//保留
        char szExeFile[MAX_PATH];//进程名
    } PROCESSENTRY32;
    */
//记住这种格式就行了,返回的句柄,存储有进程信息,可以用Process32Firs函数找出来。
    //头文件tlhelp32.h
    //HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    //创建 工具 帮助 32 快照
    HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//参数记住就行了,成功返回句柄 失败返回INVALID_HANDLE_VALUE(-1)
    if (handle == INVALID_HANDLE_VALUE) {
        cout << "获取当前系统进程快照失败" << endl;
    }
    PROCESSENTRY32 processentry32;//结构体:程序 进口 32
    //在使用这个结构之前,先设置它的大小
    processentry32.dwSize = sizeof(processentry32);
bool b=Process32First(handle, &processentry32);
    while(b) {
/*cout << "结构大小 " << processentry32.dwSize << endl;
        cout << "此进程的引用计数 " << processentry32.cntUsage << endl;
        cout << "进程ID " << processentry32.cntUsage << endl;
        cout << "进程默认堆ID " << processentry32.th32DefaultHeapID << endl;
        cout << "进程模块ID " << processentry32.th32ModuleID << endl;
        cout << "此进程开启的线程计数 " << processentry32.cntThreads << endl;
        cout << "父进程ID " << processentry32.th32ParentProcessID << endl;
        cout << "线程优先权 " << processentry32.pcPriClassBase << endl;
        cout << "保留 " << processentry32.dwFlags << endl;*/
        //cout << "进程名 " << processentry32.szExeFile << endl;
        printf("%ls\n", processentry32.szExeFile);
        printf("进程ID号:%u\n\n", processentry32.th32ProcessID);//th32ProcessID是进程ID号
        cout << endl;
        b=Process32Next(handle, &processentry32);
}
    CloseHandle(handle);//列举完后,需要调用CloseHandle函数关闭系统进程句柄
}
//创建一个线程(多线程)
DWORD _stdcall xiancheng(LPVOID lpvoid) {
    POINT p;
    while (1) {
        GetCursorPos(&p);
        HWND hwnd = WindowFromPoint(p);
        HDC hdc = GetDC(hwnd);
        Rectangle(hdc, 20, 20, 120, 120);
        Sleep(50);
    }
}
//创建一个线程(多线程)
void fun12() {
    //第一个参数不用管它,填NULL
    //第二个参数dwStackSize用于新线程的初始堆栈大小,默认为0
    //第三个lpStartAddress填函数名(指标),但这个函数必须是这种固定格式的DWORD _stdcall xiancheng(LPVOID lpParameter), 新的线程将会执行这个函数里面的代码,直到函数结束,线程死亡
    //第四个lpParameter是一自定义参数,用户可以通过这个参数,传递需要的类型,这个参数与线程函数的参数相对应
    //第五个dwCreationFlags填0表示立即执行,如果是CREATE_SUSPENDED表示挂起,直到用ResumeThread函数唤醒
    //第六个lpThreadId填NULL就行了。
    CreateThread(0,0,xiancheng,0,0,0);
    Sleep(5000);//不管创建的线程是否结束 进程都会关闭
}
//获取当前进程ID
void fun13() {
    cout << "当前进程ID:" << ::GetCurrentProcessId() << endl;
}
//在窗口输出一个位图
void fun14() {
    BITMAP bmInfo;//这个结构存储位图信息
    HBITMAP bmp;
    bmp = (HBITMAP)LoadImage(NULL, L"G:\\瓦力高清2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    //第一个参数hgdiobj是对象句柄,第二个参数cbBuffer是待写入lpvObject指针指向缓存区数据大小,第三个参数lpvObject是一个指针,指向一个缓存区。
    GetObject(bmp, sizeof(BITMAP), &bmInfo);//获取位图信息
    HWND wnd = FindWindow(L"Notepad", L"无标题.txt - 记事本");
    HDC hdc = GetDC(wnd);
    HDC memDC = ::CreateCompatibleDC(hdc);//创造兼容的DC
    SelectObject(memDC, bmp);//选入位图
    while (1)
    {
        BitBlt(hdc, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, memDC, 0, 0, SRCCOPY);//输出位图
        Sleep(200);
    }
}
//GetWindowText根据窗口句柄获得窗口标题名
void fun15() {
    POINT p;
    wchar_t ch[100] = {0};
    while (1) {
        GetCursorPos(&p);
        HWND hwnd = WindowFromPoint(p);
        GetWindowText(hwnd, ch, 100);
        printf("%ls",ch);
        cout << endl;
        Sleep(100);
    }
}
//SetWindowText根据窗口句柄设置窗口标题名
void fun16() {
    //HWND hwnd = FindWindowA("TXGuiFoundation", "Innocence.等3个会话");
    //SetWindowText(hwnd, L"李子果");
    SetWindowText((HWND)0x003E0670,L"李子果123");
}
//GetCurrentProcess获得当前线程句柄
//OpenProcessToken获得一个进程的访问令牌句柄
void fun17() {
    /*
    获得一个进程的访问令牌有什么用呢?主要是为了修改它的权限,前面在介绍结束一个进程的时候说过了,
    无法结束系统进程,是什么原因呢,原因是调用OpenProcess函数失败,无法获取系统进程句柄而引起的,
    那为什么会失败呢,权限不够,普通程序的进程没有SeDeDebug权限,而一个进程的权限是与访问令牌相关的,
    这样我们只要获取一个进程的访问令牌句柄,
    再以这个句柄为参数调用相应的函数提升进程的权限为SeDeDebug就可以获取系统进程句柄,进而结束它。
    */
//第一个参数ProcessHandle待获取的进程句柄
    //第二个参数DesiredAccess操作类型,填TOKEN_ADJUST_PRIVILEGES就行了
    //第三个TokenHandle是访问令牌句柄的指针,该参数接收句柄
//GetCurrentProcess()获取当前进程句柄,TOKEN_ADJUST_PRIVILEGES填这个,接收令牌的指针
    HANDLE handle;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,&handle);
//TOKEN_PRIVILEGES是描述进程权限的结构体
//LookupPrivilegeValue函数查看对应系统权限的特权值,返回信息到一个LUID结构体里
    //第一个参数lpSystemName通常都填NULL,本地系统调用,第二个参数lpName填要查询的权限名,如要查询的是SeDeDebug权限则取值是SE_DEBUG_NAME,第三个参数lpLuid接收其取值。
    //如LUIDluid; LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
//AdjustTokenPrivileges调整一个进程的访问令牌信息(权限)
    //第一个参数TokenHandle是令牌句柄
    //第二个是禁用所有权限标志,后面填FALSE就行了
    //第三个NewState是待刷进令牌句柄的PTOKEN_PRIVILEGES结构信息指针
    //第四个BufferLength指明TOKEN_PRIVILEGES结构大小
    //第五,六个参数填NULL就行了。
}
//提升权限 结束系统进程
void fun18() {
    //那么结合上面两个函数,提升一个进程权限制,让它能够结束系统进程的代码就是:
    HANDLE handle;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &handle);
    TOKEN_PRIVILEGES tp;
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
    tp.PrivilegeCount = 1;//tp里其它一些属性设置
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(handle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
DWORD id;
    GetWindowThreadProcessId((HWND)0x000806E6, &id);
    HANDLE ha = OpenProcess(PROCESS_ALL_ACCESS, false, id);
    cout << ha << endl;
    TerminateProcess(ha, 0);
}
//RegisterHotKey注册一个热键
void fun19() {
    //第一个参数hWnd表明热键消息(HOT_KEY)发送给哪个窗口,为NULL表明直接把消息投递给调用这个函数进程的消息队列。
    //第二个参数可以自定取值,取值范围0xC000 - 0xFFFF, 这个参数是为了程序能同时拥有多个热键而存在。
    //第三个参数fsModifiers的可选取值如下:MOD_ALT(Alt键),MOD_CONTROL(Ctrl键),MOD_SHIFT(Shift键),MOD_WIN(‘田’图标键)
    //最一个参数是一个ASCII值,指明具体和哪个非系统键组合。
    //如QQ的热键ctrl+alt+z,注册这个热键的语句是RegisterHotKey(NULL,0x0001,MOD_CONTROL|MOD_ALT,‘Z’)
    //如QQ的截图热键RegisterHotKey(NULL, 0x0001, MOD_CONTROL | MOD_ALT, 'A')
}
int main()
{
    //fun5();
    //fun8();
    fun18();
    return 0;
}
————————————————
版权声明:本文为CSDN博主「李子果」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010756046/article/details/82432312
windows.h系统函数的更多相关文章
- windows.h详解
		
参考 http://blog.csdn.net/fengningning/article/details/2306650?locationNum=1&fps=1 windows.h解构 刚开头 ...
 - 结合windows消息系统理解C#中WndProc函数和DefWndProc函数
		
Windows消息系统由3部分组成: 1.消息队列.Windows应用程序的消息是由Windows统一在一个消息队列中管理的. 2.消息循环.应用程序从Windows消息队列中获得自己 ...
 - windows.h头文件中改变光标位置的函数——SetConsoleCursorPosition
		
COORD 具体为 typedef struct COORD{ short X; short Y; } COORD,*PCOORD; 可以用来记录坐标. #include <iostre ...
 - mfc 调用Windows的API函数实现同步异步串口通信(源码)
		
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...
 - Windows 各种计时函数总结
		
本文对Windows平台下常用的计时函数进行总结,包括精度为秒.毫秒.微秒三种精度的 5种方法.分为在标准C/C++下的二种time()及clock(),标准C/C++所以使用的time()及cloc ...
 - <转>Windows 各种计时函数总结
		
本文转自MoreWindows 特此标识感谢 http://blog.csdn.net/morewindows/article/details/6854764 本文对Windows平台下常用的计时函数 ...
 - Ubuntu vim+ ctags(包含系统函数) + taglist 配置                                                    分类:            vim             ubuntu             2015-06-09 18:19    195人阅读    评论(0)    收藏
		
阅读大型代码,我们经常需要打开很多的代码文件,搜索各种定义.windows下用惯了ide的朋友,转战Linux的时候可能会觉得很难受,找不到合适的阅读工具.其实万能的vim就可以实现.下面介绍一下vi ...
 - 如何通过HOOK改变windows的API函数(找到函数的相对偏移)
		
我们知道,系统函数都是以DLL封装起来的,应用程序应用到系统函数时,应首先把该DLL加载到当前的进程空间中,调用的系统函数的入口地址,可以通过GetProcAddress函数进行获取.当系统函数进行调 ...
 - 在windows XP系统下编译和使用ffmpeg
		
最近在做流媒体开发这一块,在服务器端,所用的live555不支持mp4,avi等视频容器格式,所以打算运用ffmpeg来进行扩展.将MP4文件先运用ffmpeg进行解析,解析成live555所支持的基 ...
 
随机推荐
- win10安装JDK cmd中可以运行java,但不能用javac,解决方案
			
win10安装JDK cmd中可以运行java,但不能用javac 网上教程(1)新建->变量名"JAVA_HOME",变量值"C:\Java\jdk1.8.0_0 ...
 - 8个必备的Python GUI库
			
Python GUI 库有很多,下面给大家罗列常用的几种 GUI 库.下面介绍的这些GUI框架,能满足大部分开发人员的需要,你可以根据自己的需求,选择合适的GUI库. 很多人学习python,不知道从 ...
 - 修改linux操作系统的时间可以使用date指令 运维系统工程师必会技术
			
修改linux的时间可以使用date指令 修改日期: 时间设定成2009年5月10日的命令如下: date -s 05/10/2009 修改时间: 将系统时间设定成上午10点18分0秒的命令如下. d ...
 - 长沙做假证u
			
长沙做假证[电/薇:187ヘ1184ヘ0909同号]办各类证件-办毕业证-办离婚证,办学位证书,办硕士毕业证,办理文凭学历,办资格证,办房产证不. 这是一个简单的取最大值程序,可以用于处理 i32 数 ...
 - Fitness - 05.19
			
倒计时226天 运动45分钟,共计9组,4.7公里.拉伸10分钟. 每组跑步3分钟(6.5KM/h),走路2分钟(5.5KM/h). 上周的跑步计划中断了,本周重复第三阶段的跑步计划. 一共掉了10斤 ...
 - Stack (30)(模拟栈,输出中间数用set)
			
Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...
 - 13props    对象
			
props: { homeData: { type: Object, required: true } }, 父组件传递给子组件是对象homeData或者数组: homeData={name:'zs' ...
 - Linux服务器被入侵后的处理过程
			
突然,频繁收到一组服务器 ping 监控不可达邮件,赶紧登陆 zabbix 监控系统查看流量状况. 可见流量已经达到了 800M 左右,这肯定不正常了,马上尝试 SSH 登陆系统,不幸的事,由于网络堵 ...
 - 用于测试SqlAnalyzer1.00的十七个测试用例
			
SqlAnalyzer功能:解析SQL语句,具体到字段,表和条件,并将其整理后输出格式化文本. 1. 原文=select a from b 整理后文本= select a from b 2. 原文=s ...
 - python之class Meta用法
			
Django model中的 class Meta 详解 通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样: class Foo(mod ...