实例介绍
【实例简介】
一个摄像头驱动的类,使用方便。兼容所有支持dshow的摄像头。
【实例截图】
【核心代码】
long CCaptureVideo::initCapture(int deviceID, CAPTURECALLBACK captureCallBack, long pixelwith, long pixelhigh, long framerate, HWND hwnd) { m_captureCallBack = captureCallBack; m_24BitData = 0; m_24BitLength = 0L; HRESULT hr = initCaptureGraphBuilder();//initialize data if (FAILED(hr)) { return CAPTURE_ERR_OTHER; } //bind the object video device if(!bindFilter(deviceID, &m_BaseFilter)) { return CAPTURE_ERR_OTHER; } hr = m_GraphBuilder->AddFilter(m_BaseFilter, L"Capture Filter"); //create ISampleGrabber module hr = CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void**)&m_SampleGrabber ); if (FAILED(hr)) { return CAPTURE_ERR_OTHER; } //add Grabber Filer CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase(m_SampleGrabber); hr = m_GraphBuilder->AddFilter( pGrabBase, L"Grabber" ); if(FAILED(hr)) { return CAPTURE_ERR_OTHER; } //set media type _AMMediaType AMediaType; _AMMediaType * aMediaType = &AMediaType; ZeroMemory(aMediaType, sizeof(_AMMediaType)); aMediaType->majortype = MEDIATYPE_Video; aMediaType->subtype = MEDIASUBTYPE_RGB24; hr = m_SampleGrabber->SetMediaType(aMediaType); if (FAILED(hr)) { return CAPTURE_ERR_OTHER; } //capture the instant image hr = m_CaptureGraphBuilder2->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_BaseFilter,pGrabBase,NULL); if( FAILED(hr)) { return CAPTURE_ERR_OTHER; } //add IAMStreamConfig interface hr = m_CaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,m_BaseFilter, IID_IAMStreamConfig, (void **)&m_Config); if ( FAILED(hr) ) { return CAPTURE_ERR_OTHER; } if( pixelwith == 0 && pixelhigh == 0 ) { m_Config->GetFormat(&aMediaType);//get the media type VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) aMediaType->pbFormat; m_SampleGrabberCB->SetWidth(vih->bmiHeader.biWidth); m_SampleGrabberCB->SetHeight(vih->bmiHeader.biHeight); m_SampleGrabberCB->SetbGrabVideo(TRUE); pixelwith = vih->bmiHeader.biWidth; pixelhigh = vih->bmiHeader.biHeight; freeMediaType(aMediaType); } else { m_Config->GetFormat(&aMediaType);//get the media type VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) aMediaType->pbFormat; vih->bmiHeader.biWidth = pixelwith;//set with pixel vih->bmiHeader.biHeight = pixelhigh;//set high pixel m_Config->SetFormat(aMediaType);//设置 m_SampleGrabberCB->SetWidth(vih->bmiHeader.biWidth); m_SampleGrabberCB->SetHeight(vih->bmiHeader.biHeight); m_SampleGrabberCB->SetbGrabVideo(TRUE); pixelwith = vih->bmiHeader.biWidth; pixelhigh = vih->bmiHeader.biHeight; freeMediaType(aMediaType); } hr = m_SampleGrabber->SetBufferSamples(FALSE);//call back module hr = m_SampleGrabber->SetOneShot(FALSE); hr = m_SampleGrabber->SetCallback(m_SampleGrabberCB,1); //set capture window m_hWnd = hwnd ; if (m_hWnd == NULL) { m_VideoWindow->put_AutoShow(OAFALSE); } else { setupVideoWindow(); } //begin to capture hr = m_MediaControl->Run(); if(FAILED(hr)) { return CAPTURE_ERR_OTHER; } m_avaiable = true; if (m_SampleGrabberCB != 0) { m_SampleGrabberCB->registerCaptureCallBack(captureCallBack); } return CAPTURE_SUCCESSED; } /************************************************************************ function:release resource return type:HRESULT /************************************************************************/ void CCaptureVideo::unInitCapture() { if(m_MediaControl)m_MediaControl->StopWhenReady(); if(m_VideoWindow) { m_VideoWindow->put_Visible(OAFALSE); m_VideoWindow->put_Owner(NULL); } SAFE_RELEASE(m_MediaControl); SAFE_RELEASE(m_VideoWindow); SAFE_RELEASE(m_GraphBuilder); SAFE_RELEASE(m_BaseFilter); SAFE_RELEASE(m_SampleGrabber); SAFE_RELEASE(m_CaptureGraphBuilder2); if (m_24BitData !=NULL) { delete []m_24BitData; m_24BitData = NULL; } m_avaiable = false; } /************************************************************************ function:get data @param:with @param:high return type:BYTE * ************************************************************************/ BYTE * CCaptureVideo::get24BitData( long& with,long& high) { if (m_avaiable == false) { return 0; } with=m_SampleGrabberCB->GetWidth(); high=m_SampleGrabberCB->GetHeight(); if (m_SampleGrabberCB->GetDataBuffer()==NULL || m_SampleGrabberCB->GetDataLength()==0) return 0; long len = m_SampleGrabberCB->GetDataLength(); if (len > m_24BitLength) { delete []m_24BitData; m_24BitData = new BYTE[len]; m_24BitLength = len; } memcpy(m_24BitData,m_SampleGrabberCB->GetDataBuffer(),len); return m_24BitData; } /************************************************************************ function:enum video device @param:list return type:int /************************************************************************/ int CCaptureVideo::enumDevices(HCombleBox list) { if (!list) return -1; int id = 0; ICreateDevEnum *pCreateDevEnum; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum); if (hr != NOERROR) return -1; CComPtr<IEnumMoniker> pEm; hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0); if (hr != NOERROR) return -1; pEm->Reset(); ULONG cFetched; IMoniker *pM; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) { IPropertyBag *pBag; hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(SUCCEEDED(hr)) { VARIANT var; var.vt = VT_BSTR; hr = pBag->Read(L"FriendlyName", &var, NULL); if (hr == NOERROR) { TCHAR str[2048]; id ; WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1,(LPSTR)str, 2048, NULL, NULL); ::SendMessageA(list, CB_ADDSTRING, 0,(LPARAM)str); SysFreeString(var.bstrVal); } pBag->Release(); } pM->Release(); } return id; } /*********************************************** function:bind object device @param:deviceId @param:pFilter Filter return type:BOOL ***********************************************/ bool CCaptureVideo::bindFilter(int deviceId, IBaseFilter **pFilter) { if (deviceId < 0) return false; CComPtr<ICreateDevEnum> pCreateDevEnum; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum); if (hr != NOERROR) return false; CComPtr<IEnumMoniker> pEm; hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0); if (hr != NOERROR) return false; pEm->Reset(); ULONG cFetched; IMoniker *pM; int index = 0; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId) { IPropertyBag *pBag; hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(SUCCEEDED(hr)) { VARIANT var; var.vt = VT_BSTR; hr = pBag->Read(L"FriendlyName", &var, NULL); if (hr == NOERROR) { if (index == deviceId) pM->BindToObject(0,0, IID_IBaseFilter, (void**)pFilter); SysFreeString(var.bstrVal); } pBag->Release(); } pM->Release(); index ; } return true; } /************************************************************************ function:initialize module return type:HRESULT ************************************************************************/ HRESULT CCaptureVideo::initCaptureGraphBuilder() { HRESULT hr; // create IGraphBuilder module hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_GraphBuilder); //control interface hr = m_GraphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_MediaControl); if (FAILED(hr)) return hr; //window interface hr = m_GraphBuilder->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_VideoWindow); if (FAILED(hr)) return hr; // create ICaptureGraphBuilder2 module hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **) &m_CaptureGraphBuilder2); if (FAILED(hr)) return hr; m_CaptureGraphBuilder2->SetFiltergraph(m_GraphBuilder); return hr; } /************************************* function:make the window fixed return type:HRESULT *************************************/ HRESULT CCaptureVideo::setupVideoWindow() { HRESULT hr; hr = m_VideoWindow->put_Owner((OAHWND)m_hWnd); if (FAILED(hr)) return hr; hr = m_VideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); if (FAILED(hr)) return hr; //resizeVideoWindow,make it full if (m_VideoWindow) { CRect rc; ::GetClientRect(m_hWnd,&rc); m_VideoWindow->SetWindowPosition(0, 0, rc.right, rc.bottom); } //hr = m_VideoWindow->put_Visible(OATRUE); return hr; } /************************************* function:release the media type return type:void *************************************/ void CCaptureVideo::freeMediaType( _AMMediaType * aMediaType ) { if (aMediaType->cbFormat != 0) { CoTaskMemFree((PVOID)aMediaType->pbFormat); aMediaType->cbFormat = 0; aMediaType->pbFormat = NULL; if (aMediaType->pUnk != NULL) { aMediaType->pUnk->Release(); aMediaType->pUnk = NULL; } } } void CCaptureVideo::GetWidthAndHeight(long &outWid, long &outHei) { HRESULT hr = initCaptureGraphBuilder();//initialize data if(!bindFilter(0, &m_BaseFilter)) { return; } hr = m_CaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,m_BaseFilter, IID_IAMStreamConfig, (void **)&m_Config); if ( FAILED(hr) ) { return; } _AMMediaType AMediaType; _AMMediaType * aMediaType = &AMediaType; m_Config->GetFormat(&aMediaType);//get the media type VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) aMediaType->pbFormat; outWid = vih->bmiHeader.biWidth; outHei = vih->bmiHeader.biHeight; unInitCapture(); } void CCaptureVideo::OpenSpecifyPropertyPages() { ISpecifyPropertyPages *pSpec; CAUUID cauuid; HRESULT hr = m_BaseFilter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pSpec); if(hr == S_OK) { hr = pSpec->GetPages(&cauuid); hr = OleCreatePropertyFrame(m_hWnd, 30, 30, NULL, 1, (IUnknown **)&m_BaseFilter, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL); CoTaskMemFree(cauuid.pElems); pSpec->Release(); } // _AMMediaType AMediaType; // _AMMediaType * aMediaType = &AMediaType; // ZeroMemory(aMediaType, sizeof(_AMMediaType)); // m_Config->GetFormat(&aMediaType);//get the media type // VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) aMediaType->pbFormat; } // Tear down everything downstream of a given filter void CCaptureVideo::NukeDownstream(IBaseFilter *pf) { IPin *pP=0, *pTo=0; ULONG u; IEnumPins *pins = NULL; PIN_INFO pininfo; if (!pf) return; HRESULT hr = pf->EnumPins(&pins); pins->Reset(); while(hr == NOERROR) { hr = pins->Next(1, &pP, &u); if(hr == S_OK && pP) { pP->ConnectedTo(&pTo); if(pTo) { hr = pTo->QueryPinInfo(&pininfo); if(hr == NOERROR) { if(pininfo.dir == PINDIR_INPUT) { NukeDownstream(pininfo.pFilter); m_GraphBuilder->Disconnect(pTo); m_GraphBuilder->Disconnect(pP); m_GraphBuilder->RemoveFilter(pininfo.pFilter); } pininfo.pFilter->Release(); } pTo->Release(); } pP->Release(); } } if(pins) pins->Release(); } void CCaptureVideo::OpenPinPropertyPages() { HRESULT hr; if(m_MediaControl)m_MediaControl->Stop(); InvalidateRect(m_hWnd, NULL, TRUE); if(m_VideoWindow) { m_VideoWindow->put_Visible(OAFALSE); m_VideoWindow->put_Owner(NULL); } NukeDownstream(m_BaseFilter); IAMStreamConfig *pSC = m_Config; ISpecifyPropertyPages *pSpec; CAUUID cauuid; hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); if(hr == S_OK) { hr = pSpec->GetPages(&cauuid); hr = OleCreatePropertyFrame(m_hWnd, 30, 30, NULL, 1, (IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL); // !!! What if changing output formats couldn't reconnect // and the graph is broken? Shouldn't be possible... if(pSC) { AM_MEDIA_TYPE *pmt; // get format being used NOW hr = pSC->GetFormat(&pmt); } CoTaskMemFree(cauuid.pElems); pSpec->Release(); } #if 0 _AMMediaType AMediaType; _AMMediaType * aMediaType = &AMediaType; ZeroMemory(aMediaType, sizeof(_AMMediaType)); m_Config->GetFormat(&aMediaType);//get the media type VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) aMediaType->pbFormat; long wid = vih->bmiHeader.biWidth; long hei = vih->bmiHeader.biHeight; unInitCapture(); initCapture(0, m_captureCallBack, wid, hei, -1, m_hWnd); #else SAFE_RELEASE(m_SampleGrabber); hr = m_GraphBuilder->AddFilter(m_BaseFilter, L"Capture Filter"); hr = CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void**)&m_SampleGrabber ); CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase(m_SampleGrabber); hr = m_GraphBuilder->AddFilter( pGrabBase, L"Grabber" ); _AMMediaType AMediaType; _AMMediaType * aMediaType = &AMediaType; ZeroMemory(aMediaType, sizeof(_AMMediaType)); aMediaType->majortype = MEDIATYPE_Video; aMediaType->subtype = MEDIASUBTYPE_RGB24; hr = m_SampleGrabber->SetMediaType(aMediaType); hr = m_CaptureGraphBuilder2->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_BaseFilter,pGrabBase,NULL); hr = m_CaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,m_BaseFilter, IID_IAMStreamConfig, (void **)&m_Config); m_Config->GetFormat(&aMediaType);//get the media type VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) aMediaType->pbFormat; m_SampleGrabberCB->SetWidth(vih->bmiHeader.biWidth); m_SampleGrabberCB->SetHeight(vih->bmiHeader.biHeight); m_SampleGrabberCB->SetbGrabVideo(TRUE); freeMediaType(aMediaType); hr = m_SampleGrabber->SetBufferSamples(FALSE);//call back module hr = m_SampleGrabber->SetOneShot(FALSE); hr = m_SampleGrabber->SetCallback(m_SampleGrabberCB,1); setupVideoWindow(); hr = m_MediaControl->Run(); #endif } void CCaptureVideo::TakePhoto() { HRESULT hr; hr = m_MediaControl->Pause(); IBasicVideo *pBasicVideo; hr = m_GraphBuilder->QueryInterface(IID_IBasicVideo,(LPVOID *)&pBasicVideo); long height, width, bufSize; pBasicVideo->get_VideoHeight(&height); pBasicVideo->get_VideoWidth(&width); hr = pBasicVideo->GetCurrentImage(&bufSize, NULL); if( FAILED(hr) ) { return; } long *imgData = new long[bufSize]; memset(imgData, 0, bufSize); hr = pBasicVideo->GetCurrentImage(&bufSize, imgData); if( FAILED(hr) ) { return; } FILE *fp; fp = fopen("c:\\111.bmp", "w"); if( !fp ) { return; } else { BITMAPFILEHEADER bmphdr; BITMAPINFOHEADER bmpinfo; DWORD nWritten; memset(&bmphdr, 0, sizeof(bmphdr)); memset(&bmpinfo, 0, sizeof(bmpinfo)); bmphdr.bfType = ('M' << 8) | 'B'; bmphdr.bfSize = sizeof(bmphdr) sizeof(bmpinfo) bufSize; bmphdr.bfOffBits = sizeof(bmphdr) sizeof(bmpinfo); bmpinfo.biSize = sizeof(bmpinfo); bmpinfo.biWidth = width; bmpinfo.biHeight = height; bmpinfo.biPlanes = 1; bmpinfo.biBitCount = 24; fwrite(&bmphdr, 1, sizeof(bmphdr), fp); //fwrite(&bmpinfo, 1, sizeof(bmphdr), fp); fwrite(imgData, 1, bufSize, fp); fclose(fp); } delete[] imgData; m_MediaControl->Run(); } void CCaptureVideo::TakePhoto(CString path) { int width = m_SampleGrabberCB->GetWidth(), height=m_SampleGrabberCB->GetHeight(); //int width = 640, height = 480; BYTE* buff = m_SampleGrabberCB->GetDataBuffer(); BITMAPINFOHEADER bih; memset( &bih, 0, sizeof( bih )); bih.biSize = sizeof( bih ); bih.biWidth = width; bih.biHeight = height; bih.biPlanes = 1; bih.biBitCount = 24; CFile File(path,CFile::modeReadWrite|CFile::modeCreate); BYTE *pDib=new BYTE[sizeof(BITMAPINFOHEADER) width*height*3]; memcpy(pDib,&bih ,sizeof(BITMAPINFOHEADER)); memcpy(pDib sizeof(BITMAPINFOHEADER),buff,width*height*3); SaveDIB(pDib,File); File.Close(); delete[] pDib; } #if 1 bool CCaptureVideo::CheckCameraExist() { bool res = false; HRESULT hr = initCaptureGraphBuilder();//initialize data if (FAILED(hr)) { res = false; } else { //bind the object video device if(!bindFilter(0, &m_BaseFilter)) { res = false; } else { res = true; } } if(m_MediaControl) m_MediaControl->StopWhenReady(); if(m_VideoWindow) { m_VideoWindow->put_Visible(OAFALSE); m_VideoWindow->put_Owner(NULL); } SAFE_RELEASE(m_MediaControl); SAFE_RELEASE(m_VideoWindow); SAFE_RELEASE(m_GraphBuilder); SAFE_RELEASE(m_BaseFilter); SAFE_RELEASE(m_SampleGrabber); SAFE_RELEASE(m_CaptureGraphBuilder2); return res; } #endif void CCaptureVideo::SetBrightness(int bval) { IAMVideoProcAmp *pProcAmp = 0; HRESULT hr = m_BaseFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp); if(SUCCEEDED(hr)) { long Min, Max, Step, Default, Flags, Val; // 亮度. if( bval > 0 ) { hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step, &Default, &Flags); if(SUCCEEDED(hr)) { hr = pProcAmp->Get(VideoProcAmp_Brightness, &Val, &Flags); Val = Min (Max-Min)*bval/100; //pProcAmp->Set(VideoProcAmp_Brightness, Val, Flags); pProcAmp->Set(VideoProcAmp_Brightness, bval, Flags); } } } } int CCaptureVideo::GetBrightness(int &tmin, int &tmax) { IAMVideoProcAmp *pProcAmp = 0; HRESULT hr = m_BaseFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp); if(SUCCEEDED(hr)) { long Min, Max, Step, Default, Flags, Val; // 亮度. hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step, &Default, &Flags); tmin = Min; tmax = Max; if(SUCCEEDED(hr)) { hr = pProcAmp->Get(VideoProcAmp_Brightness, &Val, &Flags); return Val; } } } int CCaptureVideo::enumDevices(CString vid, CString pid) { int id = 0; ICreateDevEnum *pCreateDevEnum; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum); if (hr != NOERROR) return -1; CComPtr<IEnumMoniker> pEm; hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0); if (hr != NOERROR) return -1; pEm->Reset(); ULONG cFetched; IMoniker *pM; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) { CString str = ""; CString strVid, strPid; int Count = 0; IPropertyBag *pBag; hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(SUCCEEDED(hr)) { VARIANT var; var.vt = VT_BSTR; hr = pBag->Read(L"DevicePath", &var, NULL); if( hr == 0 ) { while( var.bstrVal[Count] != 0x00 ) { str = var.bstrVal[Count]; Count ; } strVid = str.Mid(str.Find("vid_") 4, 4); strPid = str.Mid(str.Find("pid_") 4, 4); if( 0 == strcmp(strVid, vid) && 0 == strcmp(strPid, pid) ) { return id; break; } } id ; pBag->Release(); } pM->Release(); } return -1; } void CCaptureVideo::SwitchAvSvideo(int mode) { IAMCrossbar *pXBar1 = NULL; HRESULT hr = m_CaptureGraphBuilder2->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, m_BaseFilter,IID_IAMCrossbar, (void**)&pXBar1); if (SUCCEEDED(hr)) { long OutputPinCount; long InputPinCount; long PinIndexRelated; long PhysicalType; long inPort = 0; long outPort = 0; pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount); for(int i =0;i<InputPinCount;i ) { pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType); if(mode==PhysicalType) { inPort = i; break; } } for( i =0;i<OutputPinCount;i ) { pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType); if(PhysConn_Video_VideoDecoder==PhysicalType) { outPort = i; break; } } if(S_OK==pXBar1->CanRoute(outPort,inPort)) { pXBar1->Route(outPort,inPort); } pXBar1->Release(); } }
好例子网口号:伸出你的我的手 — 分享!
相关软件
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论