windows消息处理机制.doc

上传人:豆**** 文档编号:29934926 上传时间:2022-08-02 格式:DOC 页数:78 大小:144KB
返回 下载 相关 举报
windows消息处理机制.doc_第1页
第1页 / 共78页
windows消息处理机制.doc_第2页
第2页 / 共78页
点击查看更多>>
资源描述

《windows消息处理机制.doc》由会员分享,可在线阅读,更多相关《windows消息处理机制.doc(78页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、windows消息处理机制消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如, 对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做TMsg,它 在Windows单元中是这样声明的: type TMsg = packed record hwnd: HWND; / /窗口句柄 message: UINT; / /消息常量标识符 wParam: WPARAM ; / 32位消息

2、的特定附加信息 lParam: LPARAM ; / 32位消息的特定附加信息 time: DWORD; / /消息创建时的时间 pt: TPoint; / /消息创建时的鼠标位置 e n d ; 消息中有什么? 是否觉得一个消息记录中的信息像希腊语一样?如果是这样,那么看一看下面的解释: hwnd 32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可 视对象的句柄(窗口、对话框、按钮、编辑框等)。 message 用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。 wParam 通常是一个与消息有关的常量值,也可能是窗口

3、或控件的句柄。 lParam 通常是一个指向内存中数据的指针。由于WParam、lParam和Pointer都是32位的,因此,它们之间可以相互转换。 Windows的消息系统是由3个部分组成的: 消息队列。Windows能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取 消息,然后分派给某个窗口。 消息循环。通过这个循环机制应用程序从消息队列中检索消息,再把它分派给适当的窗口,然 后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。 窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后 响应它。窗口过程是一个回调函数;处理了一个消息后

4、,它通常要返回一个值给Wi ndows。 注意回调函数是程序中的一种函数,它是由Windows或外部模块调用的。 一个消息从产生到被一个窗口响应,其中有5个步骤: 1) 系统中发生了某个事件。 2) Windows把这个事件翻译为消息,然后把它放到消息队列中。 3) 应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中。 4) 应用程序把消息传递给一个适当的窗口的窗口过程。 5) 窗口过程响应这个消息并进行处理。 步骤3和4构成了应用程序的消息循环。消息循环往往是Windows应用程序的核心,因为消息循环 使一个应用程序能够响应外部的事件。消息循环的任务就是从消息队列中检索消息,然后把

5、消息传递给适当的窗口。如果消息队列中没有消息,Windows就允许其他应用程序处理它们的消息。Windows操作系统最大的特点就是其图形化的操作界面,其图形化界面是建立在其消息处理机制这个基础之上的。如果不理解Windows消息处理机制,肯定无法深入的理解Windows编程。可惜很多程序员对Windows消息只是略有所闻,对其使用知之甚少,更不了解其内部实现原理,本文试着一步一步向大家披露我理解的Windows消息机制。可以说,掌握了这一部分知识,就是掌握了Windows编程中的神兵利器,灵活运用它,将会极大的提高我们的编程能力。 编辑本段Windows窗体是怎样展现在屏幕上的呢?众所周知,是

6、通过API绘制实现的。Windows操作系统提供了一系列的API函数来实现界面的绘制功能,例如:2 DrawText绘制文字2 DrawEdge绘制边框2 DrawIcon绘制图标2 BitBlt 绘制位图2 Rectangle绘制矩形2 再复杂的程序界面都是通过这个函数来实现的。那什么时候调用这些函数呢?显然我们需要一个控制中心,用来进行“发号施令”,我们还需要一个命令传达机制,将命令即时的传达到目的地。这个控制中心,就是一个动力源,就像一颗心脏,源源不断地将血液送往各处。这个命令传达机制就是Windows消息机制,Windows消息就好比是身体中的血液,它是命令传达的使者。Windows消

7、息控制中心一般是三层结构,其顶端就是Windows内核。Windows内核维护着一个消息队列,第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级窗体(Window)或控件(Control)。第二级控制中心一般是各Windows应用程序的Application对象。第三级控制中心就是Windows窗体对象,每一个窗体都有一个默认的窗体过程,这个过程负责处理各种接收到的消息。如下图所示: 说明图(注:windows指windows操作系统;窗口:即windows窗口;窗体:包括窗口,以及有句柄的控件;control指控件,控件本身也可能是一个

8、window,也可能不是;Application即应用程序,应用程序也可能不会用到Windows消息机制,这里我们专门讨论有消息循环的应用程序)消息是以固定的结构传送给应用程序的,结构如下:Public Type MSGhwnd As Longmessage As LongwParam As LonglParam As Longtime As Longpt As POINTAPIEnd Type其中hwnd是窗体的句柄,message是一个消息常量,用来表示消息的类型,wParam和lParam都是32位的附加信息,具体表示什么内容,要视消息的类型而定,time是消息发送的时间,pt是消息发送

9、时鼠标所在的位置。Windows操作系统中包括以下几种消息:1、标准Windows消息:这种消息以WM_打头。2、通知消息通知消息是针对标准Windows控件的消息。这些控个包括:按钮(Button)、组合框(ComboBox)、编辑框(TextBox)、列表框(ListBox)、ListView控件、Treeview控件、工具条(Toolbar)、菜单(Menu)等。每种消息以不同的字符串打头。3、自定义消息编程人员还可以自定义消息。二、 关于Windows句柄不是每个控件都能接收消息,转发消息和绘制自身,只有具有句柄(handle)的控件才能做到。有句柄的控件本质上都是一个窗体(windo

10、w),它们可以独立存在,可以作为其它控件的容器,而没有句柄的控件,如Label,是不能独立存在的,只能作为窗口控件的子控件,它不能绘制自身,只能依靠父窗体将它绘制来。句柄的本质是一个系统自动维护的32位的数值,在整个操作系统的任一时刻,这个数值是唯一的。但该句柄代表的窗体释放后,句柄也会被释放,这个数值又可能被其它窗体使用。也就是说,句柄的数值是动态的,它本身只是一个唯一性标识,操作系统通过句柄来识别和查找它所代表的对象。然而,并非所有的句柄都是窗体的句柄,Windows系统中还中很多其它类型的句柄,如画布(hdc)句柄,画笔句柄,画刷句柄,应用程序句柄(hInstance)等。这种句柄是不能

11、接收消息的。但不管是哪种句柄,都是系统中对象的唯一标识。本文只讨论窗体句柄。那为什么句柄使窗口具有了如此独特的特性呢?实际是都是由于消息的原因。由于有了句柄,窗体能够接收消息,也就知道了该什么时候绘制自己,绘制子控件,知道了鼠标在什么时候点击了窗口的哪个部分,从而作出相应的处理。句柄就好像是一个人的身份证,有了它,你就可以从事各种社会活动;否则的话,你要么是一个社会看不到的黑户,要么跟在别人后面,通过别人来证明你的存在。三、 消息的传送1、从消息队列获取消息:可以通过PeekMessage或GetMessage函数从Windows消息队列中获取消息。Windows保存的消息队列是以线程(Thr

12、ead)来分组的,也就是说每个线程都有自己的消息队列。2、发送消息发送消息到指定窗体一般通过以下两个函数完成:SendMessage和PostMessage。两个函数的区别在于:PostMessage函数只是向线程消息队列中添加消息,如果添加成功,则返回True,否则返回False,消息是否被处理,或处理的结果,就不知道了。而SendMessage则有些不同,它并不是把消息加入到队列里,而是直接翻译消息和调用消息处理(线程向自己发送消息才是这样),直到消息处理完成后才返回。所以,如果我们希望发送的消息立即被执行,就应该调用SendMessage。还有一点,就是SendMessage发送的消息由

13、于不会被加入到消息队列中(错:线程向其他线程发送消息也是追加到其他线程的发送消息队列的,即使这两个线程在同一个进程也是如此),所以通过PeekMessage或GetMessage是不能获取到由SendMessage发送的消息。另外,有些消息用PostMessage不会成功,比如wm_settext。所以不是所有的消息都能够用PostMessage的。还有一些其它的发送消息API函数,如PostThreadMessage,SendMessageCallback,SendMessageTimeout,SendNotifyMessage等。四、 消息循环与窗体过程消息循环是应用程序能够持续存在的根本

14、原因。如果循环退出,则应用程序就结束了。我们来看一看Delphi中封装的消息循环是怎样的:第一步:程序开始运行(Run)Application.Initialize;/初始化Application.CreateForm(TForm1, Form1);/创建主窗体Application.Run;/开始运行,准备进行消息循环如果不创建主窗体,应用程序同样可以存在和运行。第二步:开始调用消息循环(HandleMessage)procedure TApplication.Run;beginFRunning := True;tryAddExitProc(DoneApplication);if FMain

15、Form nil thenbegincase CmdShow ofSW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;end;if FShowMainForm thenif FMainForm.FWindowState = wsMinimized thenMinimize elseFMainForm.Visible := True;Repeat/注:循环开始tryHandleMessage;exceptHandleExcep

16、tion(Self);end;until Terminated;/循环结束条件end;finallyFRunning := False;end;end;第三步:消息循环中对消息的处理。procedure TApplication.HandleMessage;varMsg: TMsg;beginif not ProcessMessage(Msg) then Idle(Msg);end;function TApplication.ProcessMessage(var Msg: TMsg): Boolean;varHandled: Boolean;beginResult := False;if Pe

17、ekMessage(Msg, 0, 0, 0, PM_REMOVE) thenbeginResult := True;if Msg.Message WM_QUIT thenbeginHandled := False;if Assigned(FOnMessage) then FOnMessage(Msg, Handled);if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) andnot IsKeyMsg(Msg) and not IsDlgMsg(Msg) thenbeginTranslateMessage(Msg);Disp

18、atchMessage(Msg);end;endelseFTerminate := True;end;end;窗体过程实际上是一个回调函数。所谓的回调函数,实际上就是由Windows操作系统或外部程序调用的函数。回调函数一般都有规定的参数格式,以地址方式传递给调用者。窗口过程中是Windows操作系统调用了,在一个窗口创建的时候,在分配窗体句柄的时候就需要传入回调函数地址。那为什么我们平时编程看不到这个回调函数呢?这是由于我们的编程工具已经为我们生成了默认的窗体过程,这个过程的要做的事情就是判断不同的消息类型,然后做出不同的处理。例如可以为键盘或鼠标输入生成事件等。五、 消息与事件事件本质上是

19、对消息的封装,是IDE编程环境为了简化编程而提供的有用的工具。这个封装是在窗体过程中实现的。每种IDE封装了许多Windows的消息,例如: 事件消息OnActivateWM_ACTIVATEOnClickWM_XBUTTONDOWNOnCreateWM_CREATEOnDblClickWM_XBUTTONDBLCLICKOnKeyDownWM_KEYDOWNOnKeyPressWM_CHAROnKeyUpWIN_KEYUPOnPaintWM_PAINTOnResizeWM_SIZEOnTimerWM_TIMER MFC框架原理以及消息运行机制 收藏 (1)Windows程序内部运行机制 1,

20、windows程序设计是种事件驱动方式的程序设计,主要基于消息的。当用户需要完成某种功能时,需要调用OS某种支持,然后OS将用户的需要包装成消息,并投入到消息队列中,最后应用程序从消息队列中取走消息并进行响应。2,消息结构:typedef struct tagMSG / msg HWND hwnd; /接收消息的窗口句柄。和哪个窗口相关联。 UINT message; /消息标识。消息本身是什么。 WPARAM wParam; /消息的附加信息。具体取决于消息本身。 LPARAM lParam; DWORD time; /消息投递时间。 POINT pt; /消息投递时,光标在屏幕上的位置。

21、MSG; 3,消息队列:每个应用程序OS都为它建立一个消息队列,消息队列是个先进先出的缓冲区,其中每个元素都是一个消息,OS将生成的每个消息按先后顺序放进消息队列中,应用程序总是取走当前消息队列中的第一条消息,应用程序取走消息后便知道用户的操作和程序的状态,然后对其处理即消息响应,消息响应通过编码实现。4,使用VC编程除了良好的C基础外还需要掌握两方面:一,消息本身。不同消息所代表的用户操作和应用程序的状态。二,对于某个特定的消息来说,要让OS执行某个特定的功能去响应消息。5,Window程序入口:int WINAPI WinMain( HINSTANCE hInstance, / 当前事例句

22、柄。 HINSTANCE hPrevInstance, / 先前事例句柄。 LPSTR lpCmdLine, / 命令行指针 int nCmdShow / (窗口)显示的状态);说明:WinMain函数是Windows程序入口点函数,由OS调用,当OS启动应用程序的时候,winmain函数的参数由OS传递的。6,创建一个完整的窗口需要经过下面四个操作步骤:一,设计一个窗口类;如:WNDCLASS wndcls;二,注册窗口类; 如:RegisterClass(&wndcls);三,创建窗口; 如:CreateWindow(),CreateWindowEX();四,显示及更新窗口。如:ShowW

23、indow(),UpdateWindow();说明:创建窗口的时候一定要基于已经注册的窗口类.7,Windows提供的窗口类:typedef struct _WNDCLASS UINT style; /窗口的类型 WNDPROC lpfnWndProc; /窗口过程函数指针(回调函数) int cbClsExtra; /窗口类附加字节,为该类窗口所共享。通常0。 int cbWndExtra; /窗口附加字节。通常设为0。 HANDLE hInstance; /当前应用程序事例句柄。 HICON hIcon; /图标句柄 LoadIcon(); HCURSOR hCursor; /光标句柄 L

24、oadCursor(); HBRUSH hbrBackground; /画刷句柄 (HBRUSH)GetStockObject(); LPCTSTR lpszMenuName; /菜单名字 LPCTSTR lpszClassName; /类的名字 WNDCLASS; 8,窗口类注册:ATOM RegisterClass( CONST WNDCLASS *lpWndClass / address of structure with class / data);9,创建窗口:HWND CreateWindow( LPCTSTR lpClassName, / pointer to registere

25、d class name LPCTSTR lpWindowName, / pointer to window name DWORD dwStyle, / window style int x, / horizontal position of window int y, / vertical position of window int nWidth, / window width int nHeight, / window height HWND hWndParent, / handle to parent or owner window HMENU hMenu, / handle to m

26、enu or child-window identifier HANDLE hInstance, / handle to application instance LPVOID lpParam / pointer to window-creation data);10,显示和更新窗口窗口:BOOL ShowWindow( HWND hWnd, / handle to window int nCmdShow / show state of window);BOOL UpdateWindow( HWND hWnd / handle of window);11,消息循环:MSG msg;while(

27、GetMessage(&msg,.) /从消息队列中取出一条消息TranslateMessage(&msg); /进行消息(如键盘消息)转换DispatchMessage(&msg); /分派消息到窗口的回调函数处理,(OS调用窗口回调函数进行处理)。其中:/*The GetMessage function retrieves a message from the calling threads message queue and places it in the specified structure. /*If the function retrieves a message other

28、than WM_QUIT, the return value is nonzero.If the function retrieves the WM_QUIT message, the return value is zero. If there is an error, the return value is -1. BOOL GetMessage( LPMSG lpMsg, / address of structure with message HWND hWnd, / handle of window UINT wMsgFilterMin, / first message UINT wM

29、sgFilterMax / last message);/The TranslateMessage function translates virtual-key messages into character messages. The character messages are posted to the calling threads message queue, to be read the next time the thread calls the GetMessage or PeekMessage function. BOOL TranslateMessage( CONST M

30、SG *lpMsg / address of structure with message);/The DispatchMessage function dispatches a message to a window procedure. LONG DispatchMessage( CONST MSG *lpmsg / pointer to structure with message);12,窗口过程函数(回调函数)原型:The WindowProc function is an application-defined function that processes messages se

31、nt to a window. The WNDPROC type defines a pointer to this callback function. WindowProc is a placeholder(占位符) for the application-defined function name. LRESULT CALLBACK WindowProc( /这里WindowProc是个代号名字。 HWND hwnd, / handle to window UINT uMsg, / message identifier WPARAM wParam, / first message par

32、ameter LPARAM lParam / second message parameter);说明:两种函数调用约定(_stdcall 和 _cdecl):#define CALLBACK _stdcall /_stdcall 标准调用预定,是PASCAL 调用约定,象DELPHI使用的就是标准调用约定#define WINAPIV _cdecl / _cdecl 是C 语言形式的调用约定。主要区别:函数参数传递顺序和对堆栈的清除上。问题:除了那些可变参数的函数调用外,其余的一般都是_stdcall约定。但 C/C+编译默然的是_cdecl约定。所以如果在VC等环境中调用_stdcall约

33、定的函数,必须要在函数声明的时加上 _stdcall 修饰符,以便对这个函数的调用是使用_stdcall约定(如使用DELPHI编写的DLL时候)。(VC中可通过这途径修改:project|settings.|c/c+|.)在窗口过程函数中通过一组switch语句来对消息进行处理:如:LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) switch(uMsg) case WM_PAINT: . break;case . break;case WM_CLOSE: /DestroyWin

34、dow(hwnd); /销毁窗口,并发送WM_DESTROY消息。 break;case WM_DESTROY: /PostQuitMessage(0); /发送WM_QUIT消息到消息队列中,请求终止。 /GetMessage()取到WM_QUIT消息后,返回0,退出消息循 / 环,从而终止应用程序。 break;default: return DefWindowProc(hwnd,uMsg,wParam,lParam);/用缺省的窗口过程处理我们不感兴趣的消息(其它消息)。/这是必须的。 /switchreturn 0;/WindowProc13,DestroyWindow()函数和Pos

35、tQuitMessage()函数原型:/*The DestroyWindow function destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages。BOOL DestroyWindow( HWND hWnd / handle to window to destroy);/*The PostQuitMessage function indicates to the system that a thread has made a request to terminate (qu

36、it). It is typically used in response to a WM_DESTROY message. /*The PostQuitMessage function posts a WM_QUIT message to the threads message queue and returns immediately; the function simply indicates(预示,通知) to the system that the thread is requesting to quit at some time in the future. When the th

37、read retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system.VOID PostQuitMessage( int nExitCode / exit code);14,关于DC句柄获取:a)使用BeginPaint(),EndPaint()对。注意只能在响应WM_PAINT消息时使用。b)使用GetDc(),ReleaseDC()对。注意他们不能在响应WM_PAINT中使用。(2)C+1,c语言中,结构体stru

38、ct中不能包括函数的,而在C+中struct中可以包括函数。2,C+中结构体和类可以通用,区别主要表现在访问控制方面:struct中默认是public,而 class中默认的是private。3,构造函数最重要的作用是创建对象的本身,C+中每个类可以拥有多个构造函数,但必须至少有一个构造函数,当一个类中没有显式提供任何构造函数,C+编辑器自动提供一个默认的不带参数的构造函数,这个默认的构造函数只负责构造对象,不做任何初始化工作。但在一个类中只要自己定义一个构造函数,不管带参不带参,编辑器不再提供默认的不带参的构造函数了。构造函数没有返回值。4,析构函数当一个对象生命周期结束时候被调用来回收对象

39、占用的内存空间。一个类只需有一个析构函数。析构函数没有返回值也不的带参数。5,析构函数的作用与构造函数相反,对象超出起作用范围对应的内存空间被系统收回,或被程序用delete删除的时候,对象的析构函数被调用。6,函数的重载条件:函数的参数类型、个数不同,才能构成函数的重载。重载是发生在同一个类中。7,类是抽象的,不占用具体物理内存,只有对象是实例化的,是占用具体物理内存的。8,this指针是隐含指针,指向对象本身(this指针不是指向类的),代表了对象的地址。所有的对象调用的成员函数都是同一代码段,但每个对象都有自己的数据成员。当对象通过调用它的成员函数来访问它的数据成员的时候,成员函数除了接

40、收实参外,还接收了对象的地址,这个地址被一个隐藏的形参this所获取,通过这个this指针可以访问对象的数据成员和成员函数。9,对象中public属性的成员在外部和子类中都可以被访问;protected属性的成员在外部不能被访问,在子类中是可以访问的;private属性在子类中和外部都不能被访问。10,类的继承访问特性:(public,protected,private)a)基类中private属性成员,子类无论采用那种继承方式都不能访问。b)采用public继承,基类中的public,protected属性的成员访问特性在子类中仍然保持一致。c)采用protected继承,基类中的publi

41、c,protected属性成员访问特性在子类中变为protected.d)采用private继承,基类中的public,protected属性成员访问特性在子类中变为private.11,子类和基类的构造函数或析构函数调用顺序:当调用子类的构造函数时候先调用基类的构造函数(如果没有指明,则调用基类却省那个不带参数的构造函数;如果要指明则在子类构造函数名后加:基类名(参数))。析构函数则相反,先调用子类析构函数,后调用基类的析构函数。12,函数的覆盖:函数的覆盖是发生在发生父类和子类之间的。(函数的重载是发生在同一个类中)当子类中重写了父类的某些成员函数后,子类中的成员函数覆盖了父类的对应同名成

42、员函数。13,用父类指针访问子类对象成员时候,只能访问子类从父类继承来的那部分。(这时候外部不可以访问父类中保护和私有的部分,子类中不可访问父类私有部分。)14,多态性:在基类的的成员函数前加virturl变成虚函数,当用子类对象调用该功能的成员函数时候,子类有的就调用子类的,子类没有的就调用基类的。当C+编译器在编译的时候,发现被调用的成员函数在基类中定义的是虚函数,这个时候C+就会采用迟绑定技术(late binding),在运行的时候,依据对象的类型来确定调用的哪个函数,子类有调用子类的,子类没有的就调用基类的。如果基类中的成员函数不是虚函数,则这时候的绑定是早期绑定,在编译的时候就已经

43、确定该调用哪个函数。15,纯虚函数:在类中定义时 eg: virtual void func1()=0;纯虚函数没有函数体,含有纯虚函数的类叫做抽象类,抽象类不能实例化对象。当子类从抽象类的基类中派生出来时候,如果没有实现基类中的纯虚函数,则子类也是个抽象类,也不能实例化对象。纯虚函数被标名为不具体实现的虚成员函数,纯虚函数可以让类只具有操作的名称而不具有具体的操作的内容,让派生类在继承的时候再给出具体的定义。如果派生类没有给出基类的纯虚函数的具体定义的时候,派生类也为一个抽象类,也不能实例化对象。16,引用:变量的别名。引用需要在定义的时候用一变量或对象初始化自己。引用一旦在定义的时候初始化,就维系在一个特定的变量或对象上。引用不占用物理内存(与定义引用的目标共用同一内存)。指针变量需要占用物理内存,用来存储地址。(3)MFC程序框架的剖析1,寻找WinMain人口:在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。路径:MFC|SRC|APPMODUL.CPP:_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)/ call shared/exported WinMainr

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com