DirectDraw 与 DirectInput 的游戏编程体验-_zypsg的博客-程序员秘密

技术标签: null  编程  游戏  api  工作  delete  

代码下载(3个工程) (编辑者:链接失效)
  我想关于这个主题的文章,不算少,但也不算太多。但大多是分别介绍 DirectDraw 与 DirectInput,而并没有将其结合起来,也许你会问:“分开与合并起来并没有本质区别啊!”。其实的确没有本质区别,但那样使那些最初对游戏编程报有极大热情的爱好者感到非常失望,因为这其中的一个并不能完全满足他们的要求,并且使其感到巨大的阻力,从而失去信心。所以本文将 DirectDraw 与 DirectInput结合起来去讲一个主题就是“游戏编程”,请注意是“游戏编程”,当然这只是一个简单的桌面游戏,但这已经与先前有很大的不同了,这已不是简单的 DirectDraw或 DirectInput编程。我想你现在应该能够体会出其中的区别了。

  声明:在这之前需要你具有一定的 WIN32 API 函数的知识,并且可以熟练使用。和 DirectDraw的知识,关于DirectDraw可以参见 www.frontfree.net 中的 <<动画程序编写——DirectDraw之旅>> 1-3),或其它文章。最后是 c++ 语言,当然也要包括面向对象的那部分。在 Visual C++ .NET 编译环境下进行开发的。

  首先 ,我们还是先简要复习一下DirectDraw的概念吧!
DirectDraw本质上是显存管理程序。它最重要的性能是允许程序员直接在显存里存储和操纵位图。它使你能够利用视频硬件bliter(位块传输器)在显存内部进行位图的blit(位块传输)。用视频硬件的blitter从显存向显存进行blit比从内存向显存更快。这在64位显卡向显存提供64位数据路径的今天显得尤其重要,硬件独立于促CPU进行位块传输操作,使得CPU得以继续工作。另外DirectDraw支持显卡的其他硬件加速特性,例如对精灵和z -buffering的硬件支持。

DirectDraw的工作原理

我们这里还是用图表方式展现给大家吧!



  细心的朋友可以很明显地注意到图示中的右上角的图解中说明,表面对象有两个宽度,一个是WIDTH,一个是PITCH。WIDTH就是创建表面时所给出的那个宽度,而PITCH是表面的实际宽度,是按字节算的。在许多显卡上,PITCH和WIDTH是相等的,比如在640x480的高彩模式下,PITCH为1280。而在某些显卡上,PITCH比WIDTH要大。比如在640x480的256色模式下,当WIDTH是640时,PITCH为1024而不是640,这些显卡这样做是为了更好地进行数据对齐来提高性能或达到其它目的。所以,我们在实际编程时,为了保证程序的兼容性,必须按PITCH处理。 但这些硬件的底层问题,我们不用太关心,只要稍有了解就可以了。

下面我们再简要叙述一下,如何使用 DirectX 9.0 中提供的 DirectDraw 类库来创建对象并使用操作对象。

宏定义在先,定义删除指针和释放对象的宏

#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }


先创建一个 CDisplay 的全局对象
CDisplay就是ddutil.h中定义的类,用于处理表面之间的拷贝翻页等操作的类,再次定义一个全局变量,用于以后对指向的表面之间进行操作

CDisplay* g_pDisplay = NULL;

然后创建表面,当然可以创建很多的表面,这些表面都是离屏表面,在更新画面时,都可以用 CDisplay 类的对象中的方法,将其拷贝到后备缓冲区表面上。只要创建离屏表面,就要用到 CSurface 类。CSurface也是ddutil.h头文件中定义的类,用于对表面本身进行操作,如设置色彩键码,在此定义的图画指针。
 

CSurface* g_pBackSurface = NULL;

DirectX 中就一共用这两个类封装了 DirectDraw 对象的大部分操作,如果你觉得这还不能满足要求,那么你也可以在程序中用 DirectDraw API 函数编写程序,不过在本文中不再介绍。

这之后,我们会用到 InitDirectDraw 函数。这个函数是我们自己创建的。在此函数中作所有的 DirectDraw 的对象初始化工作。

HRESULT InitDirectDraw( HWND hWnd )
{
HRESULT hr; //接受返回值,其实是long型变量
LPDIRECTDRAWPALETTE pDDPal = NULL; //定义程序中的调色板
int iSprite; //定义与sprite个数有关的计数器
g_pDisplay = new CDisplay(); //动态开辟一个CDisplay类
if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH,
SCREEN_HEIGHT, SCREEN_BPP ) ) ) /*设置程序为全屏,并且 g_pDisplay 就是动态开辟一个CDisplay类的指针,而在这个类的域中,有一个DirectDraw主表面指针,和一个后备缓冲区表面的指针。在从我建议你可以先去阅读一下 ddutil.h 和 ddutil.cpp 文件。*/
{
MessageBox( hWnd, TEXT("This display card does not support 1024x768x8. "),
TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
return hr;
}
if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_DIRECTX ) ) ) ) //顾名思义,就是从bmp图片中获得调色板值,并赋值在pDDPal结构指针所指向的结构体中。
return hr;
if( FAILED( hr = g_pDisplay->SetPalette( pDDPal ) ) ) //用刚才从IDB_DIRECTX中获得的调色板制来设置程序调色板
return hr;
SAFE_RELEASE( pDDPal );//释放指针,在用过后,一定要释放,这是良好的编程习惯
// 用IDB_WINXP图片创建一个表面,并用g_pBackSurface指向这个表面
if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pBackSurface, MAKEINTRESOURCE( IDB_WINXP ),
SCREEN_WIDTH, SCREEN_HEIGHT ) ) )
return hr;//设置色彩键码为黑色,0代表黑色,这样在表面的拷贝过程中黑色像素的点将不会被拷贝,这样可以产生镂空效果。当然你可以任意设置关键颜色,而颜色的表示法可以用 RGB 宏定义。例如 红色:RGB( 255,0,0 ), 黑色 RGB( 255,255,255 )
if( FAILED( hr = g_pBackSurface->SetColorKey( RGB( 255,255,255 ) ) ) )
return hr;
return S_OK;
}

下面的函数是用于更新画面的。
 

HRESULT DisplayFrame()
{
HRESULT hr;
g_pDisplay->Clear( 0 ); //清空后备缓冲区表面
//将g_pBackSurface所指向的图片拷贝到后备缓冲区表面
g_pDisplay->Blt( 0, 0, g_pBackSurface, NULL );//最关键的地方在这里,请看下面的语句,只要我们一执行翻页操作,就可以将改动了的图像了显示在屏幕上了
if( FAILED( hr = g_pDisplay->Present() /*翻页操作*/) )
return hr;
return S_OK;
}

下面的函数是用于在程序失去焦点时调用的。

HRESULT RestoreSurfaces()
{
HRESULT hr;
LPDIRECTDRAWPALETTE pDDPal = NULL; /*当程序失去焦点,要保存当前的画面,请注意这里,g_pDisplay->GetDirectDraw()函数返回的才是真正的 DirectDraw 对象 */
if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) )
return hr;//在此我们还要重新创建调色板
if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )
return hr;//重新设置调色板
if( FAILED( hr = g_pDisplay->SetPalette( pDDPal ) ) )
return hr;
SAFE_RELEASE( pDDPal );//重新画出图画
if( FAILED( hr = g_pLogoSurface->DrawBitmap( MAKEINTRESOURCE( IDB_WINXP ),
SPRITE_DIAMETER, SPRITE_DIAMETER ) ) )
return hr;
return S_OK;
}

下面这个函数是释放表面指针所用的。

VOID FreeDirectDraw()
{
SAFE_DELETE( g_pBackSurface );
SAFE_DELETE( g_pDisplay );
}

我们的回顾到此结束,下面我们开始本文要介绍的一个关键技术,DirectInput 的使用。
游戏编程可不仅仅是图形程序的开发工作,实际上包含了许多方面,本文所要讲述的就是关于如何使用 DirectInput 来对键盘编程的问题。
而我们为什么要选择用 DirectInput 来处理游戏中的输入问题呢?其实用 Win32 API 函数也完全可以处理这些工作,例如其中,有一个

GetAsyncKeyState() 的函数可以返回一个指定键的当前状态是按下还是松开。这个函数还能返回该指定键在上次调用 GetAsyncKeyState() 函数以后,是否被按下过。虽然这个函数听上去很不错,但需要我们自己轮换查询每个键盘的状态。而在 DirectInput 中我们已经可以脱离这些烦琐的工作,只因它的功能更强大。

由于本文重点在二者的结合,故在此只介绍 DirectInput 中比较简单的,而且最容易上手的立即模式的工作方式。
而这里我们要用到 DirectInput 的 API 函数。有人会问,为什么在 DirectDraw 中用 DirectX 提供的类库编程,而对于 DirectInput 却直接使用要用其 API 函数呢,是因为没有提供 DirectInput 的类库吗?不是!而是因为使用类库并不很方便而且不灵活。

OK,让我们开始我们游戏编程的第二部——DirectInput编程。

前面讲 DirectDraw 时,并没有提到,微软是按 COM 来设计DirectX的,所以就有了一个 DIRECTINPUT 对象来表示输入设备,而某个具体的设备由 DIRECTINPUTDEVICE 对象来表示。也许会感到很无奈,怎么游戏编程需要这么多的知识啊,其实您也无需烦恼,只要知道一下就可以了,其实这并不;影响您的设计,而且就算您不知道,也同样可以驾驭DIRECTINPUT。

实际的建立过程是先创建一个 DIRECTINPUT 对象,然后在通过此对象的 CreateDevice 方法来创建 DIRECTINPUTDEVICE 对象。

#include <dinput.h>
#define DINPUT_BUFFERSIZE 16
LPDIRECTINPUT lpDirectInput; // DirectInput 对象实际上是一个com对象
LPDIRECTINPUTDEVICE lpKeyboard; // DirectInput 设备
BOOL InitDInput(HWND hWnd)
{
HRESULT hr;// 创建一个 DIRECTINPUT 对象
if( FAILED( hr = DirectInputCreate(hInstanceCopy, DIRECTINPUT_VERSION, &lpDirectInput, NULL)))
{// 失败提示或处理
return hr;
}// 创建一个 DIRECTINPUTDEVICE 界面
//参数 GUID_SysKeyboard 指明了建立的是键盘对象
if( FAILED( hr = lpDirectInput->CreateDevice(GUID_SysKeyboard, &lpKeyboard, NULL)))
{
// 失败提示或处理
return hr;
}// 设定为通过一个 256 字节的数组返回查询状态值
if( FAILED(hr = lpKeyboard->SetDataFormat(&c_dfDIKeyboard)))
{
// 失败提示或处理
return hr;
}// 设定协作模式为独占模式和前台模式,独占模式表面本程序在运行中占有所有键盘资源,而前台模式指出当程序具有焦点时才可以占有键盘资源
if( FAILED( hr = lpKeyboard->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
{
// 失败提示或处理
return hr;
}
// 设定缓冲区大小
// 如果不设定,缓冲区大小默认值为 0,程序就只能按立即模式工作
// 如果要用缓冲模式工作,必须使缓冲区大小超过 0
// 在此,我们没有必要设定,因为我们就用立即模式工作(还有一种缓冲模式),所有我们将其注调了

/* DIPROPDWORD property;

property.diph.dwSize = sizeof(DIPROPDWORD);
property.diph.dwHeaderSize = sizeof(DIPROPHEADER);
property.diph.dwObj = 0;
property.diph.dwHow = DIPH_DEVICE;
property.dwData = DINPUT_BUFFERSIZE;

if( FAILED(hr = lpKeyboard->SetProperty(DIPROP_BUFFERSIZE, &property.diph)))
{
// 失败
return FALSE;
}
*/
//此处是关键,我们要通过这个函数来锁定键盘,记住,所有的DirectInput资源在使用前都要锁定,在此即获得键盘资源,在知识我们刚才设定的键盘模式才能起作用
hr = lpKeyboard->Acquire();
if FAILED(hr)
{
// 失败
return FALSE;
}
return TRUE;
}


在这段代码中,我们首先定义了 lpDirectInput 和 lpKeyboard 两个指针,前者指向 DIRECTINPUT 对象,后者指向一个

DIRECTINPUTDEVICE 界面。其顺序就是这样的。这和其它COM对象的使用方法都一样,即先创建 COM 对象,然后创建界面,然后再获得
硬件资源,然后使用资源,然后释放。

通过 DirectInputCreate(), 我们为 lpDirectInput 创建了一个 DIRECTINPUT 对象。然后我们调用 CreateDevice 来建立一个DIRECTINPUTDEVICE 界面。
  
完成这些工作以后,我们便调用 DIRECTINPUTDEVICE 对象的 Acquire 方法来激活对设备的访问权限。在此要特别说明一点,任何一个

DIRECTINPUT 设备,如果未经 Acquire,是无法进行访问的。还有,当系统切换到别的进程时,必须用 Unacquire 方法来释放访问权限,在系统切换回本进程时再调用 Acquire 来重新获得访问权限。

立即模式的数据查询

HRESULT ReadImmediateData( HWND hWnd )
{
HRESULT hr;
BYTE diks[256]; // 创建键盘状态数据缓冲区存取键盘信息
int i; // 计数器
if( NULL == g_pKeyboard )
return S_OK;// 键盘状态数据缓冲区清0
ZeroMemory( &diks, sizeof(diks) );// 获得键盘所有键的信息,这只是检查一次
hr = g_pKeyboard->GetDeviceState( sizeof(diks), &diks );
if( FAILED(hr) )
{
// 如果键盘资源丢失,我们要重新获得
hr = g_pKeyboard->Acquire();
while( hr == DIERR_INPUTLOST )
hr = g_pKeyboard->Acquire();
return S_OK;
}// 进行一下轮循,处理键盘信息。
for( i = 0; i < 256; i++ )
{
if( diks[i] & 0x80 ) //记录此键的状态,低字节最高位是 1 表示按下,0 表示松开,一般用 diks[i]&0x80 来测试
{
switch(i)
{
//我们可以通过测试计数器i,来判断是哪个键被按下了。
//我们提供几个数据 UP:200 down:208 left:203 right:205 enter:28 space:57
//其实你可以用DirectX中的SamplesC++DirectInputBinKeyboard.exe程序来测试,只不过那是用
//16进制显示的。
case 200:
break;
case 0xc8:
break;
}
}
}
return S_OK;
}

请注意,上面的这段代码只是一个示例,重在使你明白其原理,但并不能满足游戏的需求,因为这其中只查询了一次键盘的全部信息,做了一次轮循,而在游戏中要周期性地查询,并轮循,这就需要你自己用Win32 API函数 SetTimer和 KillTimer 设置初始化 DirectInput 对象函数中在相应的地方设置计计时器,让windows定时向程序发送 WM_TIMER消息,你要通过此消息进行周期性地键盘查询,并在相应的地方解除计时器。

最后一个函数是用于释放指针或DirectInput对象的

void ReleaseDInput(void)
{
if (lpDirectInput)
{
if(lpKeyboard)
{
// Always unacquire the device before calling Release().
lpKeyboard->Unacquire();
lpKeyboard->Release();
lpKeyboard = NULL;
}
lpDirectInput->Release();
lpDirectInput = NULL;
}
}

在这些函数中的注释很明确,关键在于理解其原理,而怎样将他们融入到 Win32 API 程序的基本框架中的,在<<动画程序编写——DirectDraw之旅>> 1-3中的示例代码中已经解释得很明确了,在此不再赘述。不过我们提供其中的代码示例下载。同时你也可以去仔细阅读DirectX 8.0 SDK 包中的 samples multimedia directdraw fullscreenmode 或 samples multimedia directdraw windowedmode 这两个工程中的文件,因为为了我们的示例也是照这两个工程改编过来的,读者可以通过仔细阅读代码和对比我们的更改,而更加了解 DirectDraw的运行运行原理。(请注意:是 DirectX 8.0 SDK 包中的示例,而在 9.0 中 DirectX SDK 已经不提供 DirectDraw的示例代码了)

我们就用这七个函数就已经可以创造出一个小游戏了。

我们下面就要利用<<动画程序编写——DirectDraw之旅>> 1-3 中所用的代码进行进一部的游戏开发。
我们先展示一下 DirectX中 samples multimedia directdraw windowedmode 工程中的截图
在这个动画中有黑色背景,并有很多 DirectX 精灵在漂浮。



这是一个全屏的动画程序,而我们在<<动画程序编写——DirectDraw之旅>> 1-3其中做的改动就是为其加了一个背景,改屏幕分辨率 640×480 为 1024×768.注意,因为我们应用的是全屏模式,即可以独占显存资源,所以我们可以更改屏幕的分辨率。这只是做的小小的改动,而我们的目的只在于让大家更加深入了解。且看下面的这副截图:



而我们还要继续深入编程,我们的思路是,先将程序由先前的全屏程序改编成一个windows的窗口程序,然后将其所有的界面翻新,并改编 DirectX精灵为许多小蘑菇在漂浮,还要加入DirectInput 的组建,用键盘控制一个小娃娃。可以上下左右,并可以斜向飞行。
我们先将此动画的截图展现给大家



怎么样,你有什么想法,是想说:“唉,这还不好办,就是又多加了一个!”,但不要光看截图,不要忘记,我们一定让她动起来,并且是可以控制的,这就不是那么简单的事了!
什么?若有人看到这里感到有些迷茫和泄气,不禁想问:“你说了这么多,那么源代码在那里呢!,光给我们几个函数,又能做什么呢?”,如果你这么想,你也不要太急迫。我们还是先分析一下程序框架吧。

不过,还有一件重要的事情,我还是要重申一边。一定要将 DirectX 的头文件价,和lib文件夹加入到 Visual C++.NET 的默认目录中去,这样编译器就可以正确地找到它们了。
如果你不会加入,就请通过工具栏上的 Tool -> Option… 打开Option 对话框,设置如图:



好了,这样我们的准备工作就算已经做好了。

来看看我们的工程文件结构吧,还有工程中的资源。



在工程资源中我们的 ID 号是都用的字符串表示的,笔者认为这样更加方便。
我想对于工程文件中的 ddutil.cpp 和 dxutil.cpp 文件,读者如果了解有些 DirectDraw编程是不会感到陌生的,我们只是将其引入到我们的工程中了。而我们自己实际编程的文件是
outfly.cpp 文件。

我们的程序叙述如下:
首先进行宏定义,结构设置,和全局变量的声明。
后在 WinMain (windows程序的入口点)中首先初始化一切需要初始化的物件(有windows窗口,DirectDraw对象,和 DirectInput对象),在此我们就调用前文讲过的函数,但要有写改动,读者在会在后面看到的。然后进入消息循环,在其中没有消息时,程序会自动更新画面,在有消息时处理消息。
当遇到 WM_QUIT 消息后,结束整个程序。

我们在一些地方有一些小小的改动,我们来看看吧。

1 我们在 HRESULT InitDirectInput( HWND hWnd )
函数中的开始加入了

KillTimer( hWnd, 0 );
FreeDirectInput();

关掉上一次使用的计时器,并释放 DirectInput 设备。
而在最后加入了

SetTimer( hWnd, 0, 1000 / 100, NULL );

用来重新设置计时器。

2 我们在主窗口的消息处理函数中加入了

case WM_ACTIVATE: //当程序先失去焦点,而现在有重新得到焦点时,要重新锁定键盘资源
if( WA_INACTIVE != wParam && g_pKeyboard )
{
// Make sure the device is acquired, if we are gaining focus.
g_pKeyboard->Acquire();
}
break;
case WM_TIMER: //因为设置了计时器所以要处理此消息
if( FAILED( ReadImmediateData( hWnd ) ) )
{
KillTimer( hWnd, 0 );
MessageBox( NULL, _T("Error reading input state. ")
_T("The sample will now exit."),
_T("Keyboard"), MB_ICONERROR | MB_OK );
}
break;
case WM_DESTROY:// Cleanup and close the app
FreeDirectDraw();
FreeDirectInput(); // 释放资源
PostQuitMessage( 0 );
return 0L;

3 在HRESULT ReadImmediateData( HWND hWnd ) 函数中进行了这样的处理,来时时改变小娃娃的坐标。

for( i = 0; i < 256; i++ )
{
if( diks[i] & 0x80 )
{
switch(i)
{
case 200: //上键
if( g_me.fPosY > g_me.fVelY)
g_me.fPosY -= g_me.fVelY;
else
g_me.fPosY = 0;
break;
case 208: //下键
if( g_me.fPosY <= WINDOW_HEIGHT - SPRITE_DIAMETER - g_me.fVelY)
g_me.fPosY += g_me.fVelY;
else
g_me.fPosY = WINDOW_HEIGHT- SPRITE_DIAMETER;
break;
case 203://左键
if( g_me.fPosX > g_me.fVelX)
g_me.fPosX -= g_me.fVelX;
else
g_me.fPosX = 0;
break;
case 205://右键
if( g_me.fPosX <= WINDOW_WIDTH - SPRITE_DIAMETER - g_me.fVelX)
g_me.fPosX += g_me.fVelX;
else
g_me.fPosX = WINDOW_WIDTH- SPRITE_DIAMETER;
break;
}
}
}

这些只是其中一些比较重要的改动,还有许多改动,读者会在实际的程序中看到的。如果你觉得:“啊!到这里就结束了,可是我还是感到似乎莫不到头绪,就这样草草收尾了?”,其实文章并没有结束,重头戏还在后面呢,那就不是我的工作了,而是看你有没有耐心去仔细阅读代码了,因为想要把握程序的整体,与其让我将代码放在文章中,还不如读者自己在编译器中自己运行实践一下好,其实我们已经在第二个工程代码中有过详细的解释。但记住一定要按照顺序阅读 工程1,工程2 ,工程3。工程1就是 DirectX中提供的原代码,工程2就是我们改了一个背景的工程,而3就是我们讨论的工程。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zypsg/article/details/721941

智能推荐

python3中的max函数_Python3 max() 函数_瀚忄的博客-程序员秘密

Python3 max() 函数描述max() 方法返回给定参数的最大值,参数可以为序列。语法以下是 max() 方法的语法:max(x,y,z,....)参数x -- 数值表达式。y -- 数值表达式。z -- 数值表达式。返回值返回给定参数的最大值。实例以下展示了使用 max() 方法的实例:#!/usr/bin/python3print("max(80,100,1000)...

教程,word导出为pdf既要书签和链接又要高清图片_word模板导出 用书签_cbszju的博客-程序员秘密

一、谁需要这个教程:用word写论文等转成PDF,既要保留书签和超链接,又要保留高清图片。这个教程应该是全网首发,google都找不到我这样的解决办法。二、必备条件1、adobe acrobat 本人用的是破解版,adobe acrobat X ,完全安装模式安装。2、adobe acrobat 参考文章https://blog.csdn.net/weixin_30568715/article/details/96413531 安装好autobookmark 插件。装完工具栏会有这个增效工具出现

Oracle partition 表分区详解_爱游戏爱动漫的肥宅的博客-程序员秘密

随着表中行数的增多,管理和性能影响也将随之增加。备份将要花费更多时间,恢复也将 要花费更多的时间,对整个数据表的查询也将花费更多时间。通过把一个表中的行分为几个部分,可以减少大型表的管理和性能问题,以这种方式划分发表数据的方法称为对表的分区。

大数据入门教程,零基础3天快速入门大数据(2021贺岁篇)!_零基础3天快速入门大数据(贺岁篇)_黑马程序员官方的博客-程序员秘密

零基础3天快速入门大数据(2021贺岁篇),大数据入门教程,大数据教程。2021年大数据已经从单纯的技术架构和技术体系,走向了社会基础设施。2020年“新基建”就将“大数据中心”定义为数字新基础设施的重要建设内容。现在想学大数据的小伙伴越来越多了,今天就给大家分享一套大数据快速入门教程!零基础3天快速入门大数据(2021贺岁篇)http://yun.itheima.com/course/841.html?stt课程内容:1. 大数据概论和职业规划2. Linux服务器系统3. HD

爬虫小进阶——selenium_kncfkncf的博客-程序员秘密

继续练手,写了一个已知地理位置爬经纬度的代码,用selenium模拟操作浏览器。编程环境:py3假定地理位置的读取与写入均在excel中进行当数据量较大时需要调openpyxl而不是xlwt来写入数据:import xlrdfrom openpyxl import Workbookfrom selenium import webdriverimport time先将所有地理位置读入一个lis...

Xamarin Android Activity之间跳转与传值_xamarin转activity并传值_Andrewniu的博客-程序员秘密

Activity跳转与传值,主要是通过Intent类来连接其他Activity进行数据的传递。  1.不带数据跳转Intent intent = new Intent(this, typeof(Add)); StartActivity(intent);  其中的Add是跳转的Activity。  2.带数据跳转   Mai

随便推点

vue+tiptap ,基于vue的无渲染的富文本编辑器_365编辑器 vue_鸣拙的博客-程序员秘密

安装tiptap官网:github:https://github.com/ueberdosis/tiptap演示:https://www.vue365.cn/code_demo.php?id=975npm install tiptapnpm install tiptap-extensions该编辑器基于prosemiror,完全可扩展且无渲染。您可以轻松地将自定义节点添加为Vue组件。基础案例// 如果点击按钮,页面文本的样式没有改变,查看元素的标签是否已经改变,标签已改变,只是页面的样式

Android百度离线地图_-无-怨-无-悔-的博客-程序员秘密

版权声明:本文为博主原创文章,未经博主允许不得转载。http://lbsyun.baidu.com/index.php?title=androidsdk(百度地图官网地址),大家可以在官网上下载demon程序,申请自己的key后进行测试我们要清楚自己使用自己要用的离线地图功能,分为两种:一种是直接使用无具体位置信息的地图,这种情况不需要申请key;第二种情况是下载离线地

ajax前台传json到后台解析的方法以及注意事项_小屁孩的收藏的博客-程序员秘密

首先,如果是maven工程的话,需要在pom.xml文件中添加下方依赖<dependency>            <groupId>net.sf.json-lib</groupId>            <artifactId>json-lib</artifactId>            <version>...

VC: CString_EricChina的博客-程序员秘密

CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作,使得M FC在做字符串操作的时候方便了很多。不管怎样,使用CString有很多特殊的技巧,特别是 对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。   使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手 册,但囊括了大部分常见基本问题。

VS Code 正在统治代码编辑器领地!_AI科技大本营的博客-程序员秘密

出品:CSDN(ID:CSDNnews)【CSDN编者按】代码编辑器之于程序员的重要性不言而喻。长久以来,Vim、Emacs等老牌编辑器一直占据着举足轻重的地位,但是近年...

国密SM4,javaScript加密 java解密_在线sm4解密_土豆大人的博客-程序员秘密

转载自https://www.cnblogs.com/hzxy-blog/p/9355064.html前段时间因工作需要,接触到了SM算法。国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。SM1为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。SM2为非对称加密,基于ECC。该算法...

推荐文章

热门文章

相关标签