iTimothy

君看一叶舟,出没风波里


  • 首页

  • 分类

  • 归档

  • 项目

  • 关于

MFC应用程序中指针的使用

发表于 2005-03-11 | 分类于 技术控 | | 阅读次数:
字数统计: 2.3k 字 | 阅读时长 ≈ 8 分钟

VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多问题都能解决。 下面文字主要是个人在编程中指针使用的一些体会,说的不当的地方请指正。 一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,无论是多文档还是单文档,都存在指针获取和操作问题。 下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先一般获得本类(视,文档,对话框都支持)实例指针this,用this的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的功能。

1) 在View中获得Doc指针 CYouSDIDoc pDoc=GetDocument();一个视只能有一个文档。 2) 在App中获得MainFrame指针 CWinApp 中的 m_pMainWnd变量就是MainFrame的指针 也可以: CMainFrame pMain =(CMainFrame )AfxGetMainWnd(); 3) 在View中获得MainFrame指针 CMainFrame pMain=(CmaimFrame )AfxGetApp()->m_pMainWnd; 4) 获得View(已建立)指针 CMainFrame pMain=(CmaimFrame )AfxGetApp()->m_pMainWnd; CyouView pView=(CyouView )pMain->GetActiveView(); 5) 获得当前文档指针 CDocument pCurrentDoc =(CFrameWnd )m_pMainWnd->GetActiveDocument(); 6) 获得状态栏与工具栏指针 CStatusBar pStatusBar=(CStatusBar )AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); CToolBar pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

7) 如果框架中加入工具栏和状态栏变量还可以这样 (CMainFrame )GetParent()->m_wndToolBar; (CMainFrame )GetParent()->m_wndStatusBar;

8) 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu(); 9) 在任何类中获得应用程序类 用MFC全局函数AfxGetApp()获得。

10) 从文档类取得视图类的指针 我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。 CDocument类提供了两个函数用于视图类的定位: GetFirstViewPosition()和GetNextView() virtual POSITION GetFirstViewPosition() const; virtual CView* GetNextView(POSITION& rPosition) const;

注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。 GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一个POSITION类型值),GetNextView()有两个功能:返回下一个视图类的指针以及用引用调用的方式来改变传入的POSITION类型参数的值。很明显,在Test程序中,只有一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定义一个POSITION结构变量来辅助操作): CTestView* pTestView; POSITION pos=GetFirstViewPosition(); pTestView=GetNextView(pos);

这样,便可到了CTestView类的指针pTestView.执行完几句后,变量pos=NULL,因为没有下一个视图类,自然也没有下一个视图类的POSITION.但是这几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如: pView->IsKindOf(RUNTIME_CLASS(CTestView)); 即可检查pView所指是否是CTestView类。

有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下: CView CTestDoc::GetView(CRuntimeClass pClass) { CView* pView; POSITION pos=GetFirstViewPosition();

while(pos!=NULL){
    pView=GetNextView(pos);
    if(!pView->IsKindOf(pClass))
    break;
}

if(!pView->IsKindOf(pClass)){
    AfxMessageBox("Connt Locate the View.\r\n http://www.VCKBASE.com");
    return NULL;
}

return pView;

}

其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种可能:

1.pos为NULL,即已经不存在下一个视图类供操作; 2.pView已符合要求。

1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此pos是pView的下一个视图类的POSITION,完全有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一个视图类时就如引。因此需采用两次判断。 使用该函数应遵循如下格式(以取得CTestView指针为例):CTestView pTestView=(CTestView)GetView(RUNTIME_CLASS(CTestView)); RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为CRuntimeClass为指针。 至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦。

3.从一个视图类取得另一视图类的指针 综合1和2,很容易得出视图类之间互相获得指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数: (假设要从CTestAView中取得指向其它视图类的指针)CView CTestAView::GetView(CRuntimeClass pClass) { CTestDoc pDoc=(CTestDoc)GetDocument(); CView* pView; POSITION pos=pDoc->GetFirstViewPosition(); while(pos!=NULL){ pView=pDoc->GetNextView(pos); if(!pView->IsKindOf(pClass)) break; } if(!pView->IsKindOf(pClass)){ AfxMessageBox(“Connt Locate the View.”); return NULL; }

return pView;

} 这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档类成员函数。 有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如下:CTestBView pTestbView=(CTestView)GetView(RUNTIME_CLASS(CTestBView)); 11)对于单文档中也可以加入多个文档模板,但是一般的开发就使用MDI方式开发多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清楚,请查阅MSDN,(以下四个内容(11、12、13、14)来源:http://sanjianxia.myrice.com/vc/vc45.htm)

可以用CWinApp::GetFirstDocTemplatePostion获得应用程序注册的第一个文档模板的位置; 利用该值来调用CWinApp::GetNextDocTemplate函数,获得第一个CDocTemplate对象指针。 POSITION GetFirstDocTemplate( ) const; CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;

第二个函数返回由pos 标识的文档模板。POSITION是MFC定义的一个用于迭代或对象指针检索的值。通过这两个函数,应用程序可以遍历整个文档模板列表。如果被检索的文档模板是模板列表中的最后一个,则pos参数被置为NULL。

12)一个文档模板可以有多个文档,每个文档模板都保留并维护了一个所有对应文档的指针列表。 用CDocTemplate::GetFirstDocPosition函数获得与文档模板相关的文档集合中第一个文档的位置,并用POSITION值作为CDocTemplate::GetNextDoc的参数来重复遍历与模板相关的文档列表。函数原形为: viaual POSITION GetFirstDocPosition( ) const = 0; visual CDocument *GetNextDoc(POSITION & rPos) const = 0;

如果列表为空,则rPos被置为NULL.

13)在文档中可以调用CDocument::GetDocTemplate获得指向该文档模板的指针。函数原形如下: CDocTemplate * GetDocTemplate ( ) const; 如果该文档不属于文档模板管理,则返回值为NULL。

14)一个文档可以有多个视。每一个文档都保留并维护一个所有相关视的列表。CDocument::AddView将一个视连接到文档上,将该视加入到文档相联系的视的列表中,并将视的文档指针指向该文档。当有File/New、File/Open、Windows/New或Window/Split的命令而将一个新创建的视的对象连接到文档上时, MFC会自动调用该函数,框架通过文档/视的结构将文档和视联系起来。当然,程序员也可以根据自己的需要调用该函数。 Virtual POSITION GetFirstViewPosition( ) const; Virtual CView * GetNextView( POSITION &rPosition;) cosnt;

应用程序可以调用CDocument::GetFirstViewPosition返回与调用文档相联系的视的列表中的第一个视的位置,并调用CDocument::GetNextView返回指定位置的视,并将rPositon的值置为列表中下一个视的POSITION值。如果找到的视为列表中的最后一个视,则将rPosition置为NULL.

15)从一个视图类取得另一视图类的指针 这个应用在多视的应用程序中很多见,一般如果自己在主程序或者主框架中做好变量记号,也可以获得,还有比较通用的就是用文档类作中转,以文档类的视图遍历定位,取得另一个视图类。这个功能从本文第10项中可以得到。

这些资料大部分都是从网上和MSDN中获得的,写这个文档就是为了让大家不用再寻找,列出标题,可操作性更强。

如何把一个程序注册成系统服务

发表于 2005-02-21 | 分类于 技术控 | | 阅读次数:
字数统计: 490 字 | 阅读时长 ≈ 2 分钟

//注册并启动/终止服务 BOOL RegisterServer(LPCTSTR lpServiceName,LPCTSTR lpDisplayName,LPCTSTR lpBinaryPathName) { SC_HANDLE hSCManager = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE); if(hSCManager == NULL) { return FALSE; }

if(CreateService(hSCManager,lpServiceName,lpDisplayName,
    SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,
    SERVICE_ERROR_NORMAL,lpBinaryPathName,NULL,NULL,NULL,NULL,NULL))
{
    printf("RegisterServer...\r\n");

    CloseServiceHandle(hSCManager);
    return TRUE;
}
else
{
    printf("RegisterServer Error Code = %d\r\n",GetLastError());

    CloseServiceHandle(hSCManager);
    return FALSE;
}

}

BOOL ExecuteService(LPCTSTR lpServiceName) { SC_HANDLE hSCManager,hService; hSCManager = OpenSCManager(0,0,SC_MANAGER_ALL_ACCESS); if(hSCManager == NULL) { return FALSE; }

hService = OpenService(hSCManager,lpServiceName,SERVICE_ALL_ACCESS);
if(hService == NULL)
{
    CloseServiceHandle(hSCManager);
    return FALSE;
}

if(StartService(hService,0,NULL))
{
    printf("StartService...\r\n");

    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
    return TRUE;
}
else
{
    printf("StartService Error Code = %d\r\n",GetLastError());

    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
    return FALSE;
}

}

BOOL TerminateService(LPCTSTR lpServiceName) { SC_HANDLE hSCManager,hService; hSCManager = OpenSCManager(0,0,SC_MANAGER_ALL_ACCESS); if(hSCManager == NULL) { return FALSE; }

hService = OpenService(hSCManager,lpServiceName,SERVICE_ALL_ACCESS);
if(hService == NULL)
{
    CloseServiceHandle(hSCManager);
    return FALSE;
}

if(StartService(hService,0,NULL))
{
    SERVICE_STATUS ServerStatus;
    ControlService(hService,SERVICE_CONTROL_STOP,&ServerStatus;);

    printf("TerminateService...\r\n");

    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
    return TRUE;
}
else
{
    printf("TerminateService Error Code = %d\r\n",GetLastError());

    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
    return FALSE;
}

}

//要做成服务的EXE必须这样写

#include

#include

#include

#define SERVERNAME “CooldogServer”

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv); void WINAPI ServiceControl(DWORD nControlCode); BOOL ExecuteService(); void TerminateService(); DWORD WINAPI ServiceProc(LPVOID lpParameter); BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,DWORD dwWaitHint);

SERVICE_STATUS_HANDLE hServiceStatus; DWORD ServiceCurrentStatus; HANDLE hServiceThread; BOOL bServiceRunning; HANDLE hServiceEvent;

void main(int argc, char* argv[]) { SERVICE_TABLE_ENTRY ServiceTable[] = { {SERVERNAME,(LPSERVICE_MAIN_FUNCTION)ServiceMain}, {NULL,NULL} };

if(!StartServiceCtrlDispatcher(ServiceTable))
{
    printf("RegisterServer First");
}

}

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { hServiceStatus = RegisterServiceCtrlHandler(SERVERNAME,(LPHANDLER_FUNCTION)ServiceControl); if(!hServiceStatus || !UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,1,3000)) { return; }

hServiceEvent = CreateEvent(0,TRUE,FALSE,0);
if(!hServiceEvent || !UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,2,1000))
{
    return;
}

if(!ExecuteService())
{
    return;
}

ServiceCurrentStatus = SERVICE_RUNNING;

if(!UpdateServiceStatus(SERVICE_RUNNING,NO_ERROR,0,0,0))
{
    return;
}

WaitForSingleObject(hServiceEvent,INFINITE);
CloseHandle(hServiceEvent);

}

void WINAPI ServiceControl(DWORD dwControlCode) { switch(dwControlCode) { case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: ServiceCurrentStatus = SERVICE_STOP_PENDING; UpdateServiceStatus(SERVICE_STOP_PENDING,NO_ERROR,0,1,3000); TerminateService(); return; default: break; }

UpdateServiceStatus(ServiceCurrentStatus,NO_ERROR,0,0,0);

}

BOOL ExecuteService() { DWORD dwThreadID; hServiceThread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)ServiceProc,0,0,&dwThreadID;);

if(hServiceThread != NULL)
{
    bServiceRunning = TRUE;
    return TRUE;
}
else
{
    return FALSE;
}

}

void TerminateService() { bServiceRunning = FALSE; SetEvent(hServiceEvent); UpdateServiceStatus(SERVICE_STOPPED,NO_ERROR,0,0,0); }

DWORD WINAPI ServiceProc(LPVOID lpParameter)//在这个函数里面添加你想要的操作 { while(bServiceRunning) { Beep(450,150); Sleep(4000); }

return 0;

}

BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,DWORD dwWaitHint) { SERVICE_STATUS ServiceStatus; ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ServiceStatus.dwCurrentState = dwCurrentState;

if(dwCurrentState == SERVICE_START_PENDING)
{
    ServiceStatus.dwControlsAccepted = 0;
}
else
{
    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
}

if(dwServiceSpecificExitCode == 0)
{
    ServiceStatus.dwWin32ExitCode = dwWin32ExitCode;
}
else
{
    ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
}

ServiceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
ServiceStatus.dwCheckPoint = dwCheckPoint;
ServiceStatus.dwWaitHint = dwWaitHint;

if(!SetServiceStatus(hServiceStatus,&ServiceStatus;))
{
    TerminateService();
    return FALSE;
}

return TRUE;

}

数据类型转换示例

发表于 2005-02-17 | 分类于 技术控 | | 阅读次数:
字数统计: 819 字 | 阅读时长 ≈ 3 分钟

刚接触VC编程的朋友往往对许多数据类型的转换感到迷惑不解,本文将介绍一些常用数据类型的使用。

我们先定义一些常见类型变量借以说明

int i = 100; long l = 2001; float f=300.2; double d=12345.119; char username[]=”女侠程佩君”; char temp[200]; char *buf; CString str; _variant_t v1; _bstr_t v2;

一、其它数据类型转换为字符串

短整型(int) itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制 itoa(i,temp,2); ///按二进制方式转换 长整型(long) ltoa(l,temp,10);

二、从其它包含字符串的变量中获取指向该字符串的指针

CString变量 str = “2008北京奥运”; buf = (LPSTR)(LPCTSTR)str; BSTR类型的_variant_t变量 v1 = (_bstr_t)”程序员”; buf = _com_util::ConvertBSTRToString((_bstr_t)v1);

三、字符串转换为其它数据类型 strcpy(temp,”123”);

短整型(int) i = atoi(temp); 长整型(long) l = atol(temp); 浮点(double) d = atof(temp);

四、其它数据类型转换到CString 使用CString的成员函数Format来转换,例如:

整数(int) str.Format(“%d”,i); 浮点数(float) str.Format(“%f”,i); 字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值 str = username;

五、BSTR、_bstr_t与CComBSTR

CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。 char *转换到BSTR可以这样: BSTR b=_com_util::ConvertStringToBSTR

(“数据”);///使用前需要加上头文件comutil.h 反之可以使用char *p=_com_util::ConvertBSTRToString(b);

六、VARIANT 、_variant_t 与 COleVariant

VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关

于结构体tagVARIANT的定义。 对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,

再对联合结构中相同数据类型的变量赋值,举个例子: VARIANT va; int a=2001; va.vt=VT_I4;///指明整型数据 va.lVal=a; ///赋值

对于不马上赋值的VARIANT,最好先用

Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质

是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:

unsigned char bVal; VT_UI1 short iVal; VT_I2 long lVal; VT_I4 float fltVal; VT_R4 double dblVal; VT_R8 VARIANT_BOOL boolVal; VT_BOOL SCODE scode; VT_ERROR CY cyVal; VT_CY DATE date; VT_DATE BSTR bstrVal; VT_BSTR IUnknown FAR punkVal; VT_UNKNOWN IDispatch FAR pdispVal; VT_DISPATCH SAFEARRAY FAR parray; VT_ARRAY| unsigned char FAR pbVal; VT_BYREF|VT_UI1 short FAR piVal; VT_BYREF|VT_I2 long FAR plVal; VT_BYREF|VT_I4 float FAR pfltVal; VT_BYREF|VT_R4 double FAR pdblVal; VT_BYREF|VT_R8 VARIANT_BOOL FAR pboolVal; VT_BYREF|VT_BOOL SCODE FAR pscode; VT_BYREF|VT_ERROR CY FAR pcyVal; VT_BYREF|VT_CY DATE FAR pdate; VT_BYREF|VT_DATE BSTR FAR pbstrVal; VT_BYREF|VT_BSTR IUnknown FAR FAR ppunkVal; VT_BYREF|VT_UNKNOWN IDispatch FAR FAR ppdispVal; VT_BYREF|VT_DISPATCH SAFEARRAY FAR FAR pparray; VT_ARRAY| VARIANT FAR pvarVal; VT_BYREF|VT_VARIANT void FAR* byref; VT_BYREF

_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,

其构造函数会自动处理这些数据类型。 例如: long l=222; ing i=100; _variant_t lVal(l); lVal = (long)i;

COleVariant的使用与_variant_t的方法基本一样,请参考如下例子: COleVariant v3 = “字符串”, v4 = (long)1999; CString str =(BSTR)v3.pbstrVal; long i = v4.lVal;

七、其它

对消息的处理中我们经常需要将WPARAM或LPARAM

等32位数据(DWORD)分解成两个16位数据(WORD),例如: LPARAM lParam; WORD lovalue = LOWORD(lParam);///取低16位 WORD hivalue = HIWORD(lParam);///取高16位 对于16位的数据(WORD)我们可以用同样的方法分解成

高低两个8位数据(BYTE),例如: WORD wvalue; BYTE lovalue = LOBYTE(wvalue);///取低8位 BYTE hivalue = HIBYTE(wvalue);///取高8位

截屏操作

发表于 2005-02-06 | 分类于 技术控 | | 阅读次数:
字数统计: 81 字 | 阅读时长 ≈ 1 分钟

OnInitDialog中: // TODO: Add extra initialization here CDC dc; CBitmap *pBmp = NULL; dc.CreateDC(“DISPLAY”, NULL, NULL, NULL);

pMemDC = new CDC; if (!pMemDC) return FALSE; pMemDC->CreateCompatibleDC(&dc;);

pBmp = new CBitmap; if (!pBmp) return FALSE; pBmp->CreateCompatibleBitmap(&dc;, 1024, 768); pMemDC->SelectObject(pBmp); ShowWindow(SW_HIDE);

pMemDC->BitBlt(0, 0, 1024, 768, &dc;, 0, 0, SRCCOPY);

dc.DeleteDC(); pBmp->DeleteObject(); delete pBmp; OnPaint中: CPaintDC dc(this); dc.BitBlt(0,0,1024, 768, pMemDC, 0, 0, SRCCOPY);

枚举特定进程的所有线程列表

发表于 2005-02-04 | 分类于 技术控 | | 阅读次数:
字数统计: 216 字 | 阅读时长 ≈ 1 分钟

The following example obtains a list of running threads for the specified process. First, the RefreshThreadList function takes a snapshot of the currently executing threads in the system using the CreateToolhelp32Snapshot function, then it walks through the list recorded in the snapshot, using the Thread32First and Thread32Next functions. The parameter for RefreshThreadList is the identifier of the process whose threads will be listed.

#include

#include

#include

BOOL RefreshThreadList (DWORD dwOwnerPID) { HANDLE hThreadSnap = NULL; BOOL bRet = FALSE; THREADENTRY32 te32 = {0};

// Take a snapshot of all threads currently in the system.

hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE)
    return (FALSE);

// Fill in the size of the structure before using it.

te32.dwSize = sizeof(THREADENTRY32);

// Walk the thread snapshot to find all threads of the process.
// If the thread belongs to the process, add its information
// to the display list.

if (Thread32First(hThreadSnap, &te32;))
{
    do
    {
        if (te32.th32OwnerProcessID == dwOwnerPID)
        {
            printf( "\nTID\t\t%d\n", te32.th32ThreadID);
            printf( "Owner PID\t%d\n", te32.th32OwnerProcessID);
            printf( "Delta Priority\t%d\n", te32.tpDeltaPri);
            printf( "Base Priority\t%d\n", te32.tpBasePri);
        }
    }
    while (Thread32Next(hThreadSnap, &te32;));
    bRet = TRUE;
}
else
    bRet = FALSE;          // could not walk the list of threads

// Do not forget to clean up the snapshot object.

CloseHandle (hThreadSnap);

return (bRet);

}

TAB中加入子窗口

发表于 2005-02-04 | 分类于 技术控 | | 阅读次数:
字数统计: 60 字 | 阅读时长 ≈ 1 分钟

m_Tab.InsertItem(0,”第一页”); m_Tab.InsertItem(1,”第二页”); m_Tab.InsertItem(2,”第三页”); m_Tab.InsertItem(3,”第四页”);

m_PageA.Create(IDD_PROPPAGE_A,&m;_Tab);
m_PageB.Create(IDD_PROPPAGE_B,&m;_Tab);
m_PageC.Create(IDD_PROPPAGE_C,&m;_Tab);
m_PageD.Create(IDD_PROPPAGE_D,&m;_Tab);

m_PageA.ShowWindow(SW_SHOW);
m_PageB.ShowWindow(SW_HIDE);
m_PageC.ShowWindow(SW_HIDE);
m_PageD.ShowWindow(SW_HIDE);

RICHEDIT中插入GIF

发表于 2005-02-02 | 分类于 技术控 | | 阅读次数:
字数统计: 467 字 | 阅读时长 ≈ 2 分钟

用qq的ImageOle.dll

// MyRichEdit.cpp : implementation file //

#include “stdafx.h”

#include “ZJP.h”

#include “MyRichEdit.h”

#include “Richole.h”

#import “E:\Program files\tencent\qq\ImageOle.dll” named_guids

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE static char THIS_FILE[] = FILE;

#endif

///////////////////////////////////////////////////////////////////////////// // CMyRichEdit

CMyRichEdit::CMyRichEdit() { }

CMyRichEdit::~CMyRichEdit() { }

BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl) //{AFX_MSG_MAP(CMyRichEdit) // NOTE - the ClassWizard will add and remove mapping macros here. //}AFX_MSG_MAP END_MESSAGE_MAP()

///////////////////////////////////////////////////////////////////////////// // CMyRichEdit message handlers

void CMyRichEdit::InsertGraphics(CString strPicPath) { LPLOCKBYTES lpLockBytes = NULL; SCODE sc; HRESULT hr; //print to RichEdit’ s IClientSite LPOLECLIENTSITE m_lpClientSite; //A smart point to IAnimator ImageOleLib::IGifAnimatorPtr m_lpAnimator; //ptr 2 storage LPSTORAGE m_lpStorage; //the object 2 b insert 2 LPOLEOBJECT m_lpObject; //Create lockbytes sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes;); if (sc != S_OK) AfxThrowOleException(sc); ASSERT(lpLockBytes != NULL); //use lockbytes to create storage sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE ¦STGM_CREATE ¦STGM_READWRITE, 0, &m;_lpStorage); if (sc != S_OK) { VERIFY(lpLockBytes->Release() == 0); lpLockBytes = NULL; AfxThrowOleException(sc); } ASSERT(m_lpStorage != NULL); //get the ClientSite of the very RichEditCtrl GetIRichEditOle()->GetClientSite(&m;_lpClientSite); ASSERT(m_lpClientSite != NULL); try { //Initlize COM interface

            hr  =  ::CoInitialize(NULL)  ;//(  NULL,  COINIT_APARTMENTTHREADED  );
            if(  FAILED(hr)  )
                        _com_issue_error(hr);

            //Get  GifAnimator  object
            //here,  I  used  a  smart  point,  so  I  do  not  need  to  free  it
            hr  =  m_lpAnimator.CreateInstance(ImageOleLib::CLSID_GifAnimator);
            if(  FAILED(hr)  )
                                    _com_issue_error(hr);
            //COM  operation  need  BSTR,  so  get  a  BSTR
            BSTR  path  =  strPicPath.AllocSysString();

            //Load  the  gif
            hr  =  m_lpAnimator->LoadFromFile(path);
            if(  FAILED(hr)  )
                        _com_issue_error(hr);

            TRACE0(  m_lpAnimator->GetFilePath()  );

            //get  the  IOleObject
            hr  =  m_lpAnimator.QueryInterface(IID_IOleObject,  (void**)&m;_lpObject);
            if(  FAILED(hr)  )
                        _com_issue_error(hr);

            //Set  it  2  b  inserted
            OleSetContainedObject(m_lpObject,  TRUE);

//2  insert  in  2  richedit,  you  need  a  struct  of  REOBJECT
            REOBJECT  reobject;
            ZeroMemory(&reobject;,  sizeof(REOBJECT));

            reobject.cbStruct  =  sizeof(REOBJECT);
            CLSID  clsid;
            sc  =  m_lpObject->GetUserClassID(&clsid;);
            if  (sc  !=  S_OK)
                        AfxThrowOleException(sc);
            //set  clsid
            reobject.clsid  =  clsid;
            //can  be  selected
            reobject.cp  =  REO_CP_SELECTION;
            //content,  but  not  static
            reobject.dvaspect  =  DVASPECT_CONTENT;
            //goes  in  the  same  line  of  text  line
            reobject.dwFlags  =  REO_BELOWBASELINE;  //REO_RESIZABLE    ¦
            reobject.dwUser  =  0;
            //the  very  object
            reobject.poleobj  =  m_lpObject;
            //client  site  contain  the  object
            reobject.polesite  =  m_lpClientSite;
            //the  storage
            reobject.pstg  =  m_lpStorage;

            SIZEL  sizel;
            sizel.cx  =  sizel.cy  =  0;
            reobject.sizel  =  sizel;
            HWND  hWndRT  =  this->m_hWnd;
            //Sel  all  text

// ::SendMessage(hWndRT, EM_SETSEL, 0, -1); // DWORD dwStart, dwEnd; // ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart;, (LPARAM)&dwEnd;); // ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1); //Insert after the line of text GetIRichEditOle()->InsertObject(&reobject;); ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); VARIANT_BOOL ret; //do frame changing ret = m_lpAnimator->TriggerFrameChange(); //show it m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, m_hWnd, NULL); m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, NULL);

            //redraw  the  window  to  show  animation
            RedrawWindow();

            if  (m_lpClientSite)
            {
                        m_lpClientSite->Release();
                        m_lpClientSite  =  NULL;
            }
            if  (m_lpObject)
            {
                        m_lpObject->Release();
                        m_lpObject  =  NULL;
            }
            if  (m_lpStorage)
            {
                        m_lpStorage->Release();
                        m_lpStorage  =  NULL;
            }

            SysFreeString(path);
}
catch(  _com_error  e  )
{
            AfxMessageBox(e.ErrorMessage());
            ::CoUninitialize();
}

}

根据文件句柄,获取文件名

发表于 2005-01-31 | 分类于 技术控 | | 阅读次数:
字数统计: 223 字 | 阅读时长 ≈ 1 分钟

#include

#include

#include

#include

#include

#define BUFSIZE 512

BOOL GetFileNameFromHandle(HANDLE hFile) { BOOL bSuccess = FALSE; TCHAR pszFilename[MAX_PATH+1]; HANDLE hFileMap;

// Get the file size. DWORD dwFileSizeHi = 0; DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi;);

if( dwFileSizeLo == 0 && dwFileSizeHi == 0 ) { printf(“Cannot map a file with a length of zero.\n”); return FALSE; }

// Create a file mapping object. hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 1, NULL);

if (hFileMap) { // Create a file mapping to get the file name. void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);

if (pMem)
{
  if (GetMappedFileName (GetCurrentProcess(),
                         pMem,
                         pszFilename,
                         MAX_PATH))
  {

    // Translate path with device name to drive letters.
    TCHAR szTemp[BUFSIZE];
    szTemp[0] = '\0';

    if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
    {
      TCHAR szName[MAX_PATH];
      TCHAR szDrive[3] = TEXT(" :");
      BOOL bFound = FALSE;
      TCHAR* p = szTemp;

      do
      {
        // Copy the drive letter to the template string
        *szDrive = *p;

        // Look up each device name
        if (QueryDosDevice(szDrive, szName, BUFSIZE))
        {
          UINT uNameLen = _tcslen(szName);

          if (uNameLen < MAX_PATH)
          {
            bFound = _tcsnicmp(pszFilename, szName,
                uNameLen) == 0;

            if (bFound)
            {
              // Reconstruct pszFilename using szTemp
              // Replace device path with DOS path
              TCHAR szTempFile[MAX_PATH];
              _stprintf(szTempFile,
                        TEXT("%s%s"),
                        szDrive,
                        pszFilename+uNameLen);
              _tcsncpy(pszFilename, szTempFile, MAX_PATH);
            }
          }
        }

        // Go to the next NULL character.
        while (*p++);
      } while (!bFound && *p); // end of string
    }
  }
  bSuccess = TRUE;
  UnmapViewOfFile(pMem);
}

CloseHandle(hFileMap);

} printf(“File name is %s\n”, pszFilename); return(bSuccess); }

SQL SERVER 与ACCESS、EXCEL的数据转换

发表于 2005-01-31 | 分类于 技术控 | | 阅读次数:
字数统计: 931 字 | 阅读时长 ≈ 4 分钟

熟悉SQL SERVER 2000的数据库管理员都知道,其DTS可以进行数据的导入导出,其实,我们也可以使用Transact-SQL语句进行导入导出操作。在Transact-SQL语句中,我们主要使用OpenDataSource函数、OPENROWSET 函数,关于函数的详细说明,请参考SQL联机帮助。利用下述方法,可以十分容易地实现SQL SERVER、ACCESS、EXCEL数据转换,详细说明如下:

一、 SQL SERVER 和ACCESS的数据导入导出

常规的数据导入导出:

使用DTS向导迁移你的Access数据到SQL Server,你可以使用这些步骤:

  1在SQL SERVER企业管理器中的Tools(工具)菜单上,选择Data Transformation

  2Services(数据转换服务),然后选择 czdImport Data(导入数据)。

  3在Choose a Data Source(选择数据源)对话框中选择Microsoft Access as the Source,然后键入你的.mdb数据库(.mdb文件扩展名)的文件名或通过浏览寻找该文件。

  4在Choose a Destination(选择目标)对话框中,选择Microsoft OLE DB Prov ider for SQL Server,选择数据库服务器,然后单击必要的验证方式。

  5在Specify Table Copy(指定表格复制)或Query(查询)对话框中,单击Copy tables(复制表格)。

6在Select Source Tables(选择源表格)对话框中,单击Select All(全部选定)。下一步,完成。

Transact-SQL语句进行导入导出:

  1. 在SQL SERVER里查询access数据:

– ======================================================

SELECT *

FROM OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=”c:\DB.mdb”;User ID=Admin;Password=’)…表名


  1. 将access导入SQL server

– ======================================================

在SQL SERVER 里运行:

SELECT *

INTO newtable

FROM OPENDATASOURCE (‘Microsoft.Jet.OLEDB.4.0’,

'Data Source="c:\DB.mdb";User ID=Admin;Password=' )...表名

  1. 将SQL SERVER表里的数据插入到Access表中

– ======================================================

在SQL SERVER 里运行:

insert into OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=” c:\DB.mdb”;User ID=Admin;Password=’)…表名

(列名1,列名2)

select 列名1,列名2 from sql表

实例:

insert into OPENROWSET(‘Microsoft.Jet.OLEDB.4.0’,

‘C:\db.mdb’;’admin’;’’, Test)

select id,name from Test

INSERT INTO OPENROWSET(‘Microsoft.Jet.OLEDB.4.0’, ‘c:\trade.mdb’; ‘admin’; ‘’, 表名)

SELECT *

FROM sqltablename


二、 SQL SERVER 和EXCEL的数据导入导出

1、在SQL SERVER里查询Excel数据:

– ======================================================

SELECT *

FROM OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=”c:\book1.xls”;User ID=Admin;Password=;Extended properties=Excel 5.0’)…[Sheet1$]

下面是个查询的示例,它通过用于 Jet 的 OLE DB 提供程序查询 Excel 电子表格。

SELECT * FROM OpenDataSource ( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=”c:\Finance\account.xls”;User ID=Admin;Password=;Extended properties=Excel 5.0’)…xactions

2、将Excel的数据导入SQL server :

– ======================================================

SELECT * into newtable

FROM OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=”c:\book1.xls”;User ID=Admin;Password=;Extended properties=Excel 5.0’)…[Sheet1$]

实例:

SELECT * into newtable

FROM OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=”c:\Finance\account.xls”;User ID=Admin;Password=;Extended properties=Excel 5.0’)…xactions


3、将SQL SERVER中查询到的数据导成一个Excel文件

– ======================================================

T-SQL代码:

EXEC master..xp_cmdshell ‘bcp 库名.dbo.表名out c:\Temp.xls -c -q -S”servername” -U”sa” -P””‘

参数:S 是SQL服务器名;U是用户;P是密码

说明:还可以导出文本文件等多种格式

实例:EXEC master..xp_cmdshell ‘bcp saletesttmp.dbo.CusAccount out c:\temp1.xls -c -q -S”pmserver” -U”sa” -P”sa”‘

EXEC master..xp_cmdshell ‘bcp “SELECT au_fname, au_lname FROM pubs..authors ORDER BY au_lname” queryout C:\ authors.xls -c -Sservername -Usa -Ppassword’

在VB6中应用ADO导出EXCEL文件代码:

Dim cn As New ADODB.Connection

cn.open “Driver={SQL Server};Server=WEBSVR;DataBase=WebMis;UID=sa;WD=123;”

cn.execute “master..xp_cmdshell ‘bcp “SELECT col1, col2 FROM 库名.dbo.表名” queryout E:\DT.xls -c -Sservername -Usa -Ppassword’”


4、在SQL SERVER里往Excel插入数据:

– ======================================================

insert into OpenDataSource( ‘Microsoft.Jet.OLEDB.4.0’,

‘Data Source=”c:\Temp.xls”;User ID=Admin;Password=;Extended properties=Excel 5.0’)…table1 (A1,A2,A3) values (1,2,3)

T-SQL代码:

INSERT INTO

OPENDATASOURCE(‘Microsoft.JET.OLEDB.4.0’,

‘Extended Properties=Excel 8.0;Data source=C:\training\inventur.xls’)…[Filiale1$]

(bestand, produkt) VALUES (20, ‘Test’)


总结:利用以上语句,我们可以方便地将SQL SERVER、ACCESS和EXCEL电子表格软件中的数据进行转换,为我们提供了极大方便!

ShellExecute用法种种

发表于 2005-01-20 | 分类于 技术控 | | 阅读次数:
字数统计: 331 字 | 阅读时长 ≈ 1 分钟

Q: 如何打开一个应用程序? ShellExecute(this->m_hWnd,”open”,”calc.exe”,””,””, SW_SHOW );或 ShellExecute(this->m_hWnd,”open”,”notepad.exe”,”c:\MyLog.log”,””,SW_SHOW );正如您所看到的,我并没有传递程序的完整路径。

Q: 如何打开一个同系统程序相关连的文档?ShellExecute(this->m_hWnd,”open”,”c:\abc.txt”,””,””,SW_SHOW );

Q: 如何打开一个网页? ShellExecute(this->m_hWnd,”open”,”http://www.google.com","","", SW_SHOW );

Q: 如何激活相关程序,发送EMAIL? ShellExecute(this->m_hWnd,”open”,”mailto:[email protected]“,””,””, SW_SHOW );

Q: 如何用系统打印机打印文档? ShellExecute(this->m_hWnd,”print”,”c:\abc.txt”,””,””, SW_HIDE);

Q: 如何用系统查找功能来查找指定文件? ShellExecute(m_hWnd,”find”,”d:\nish”,NULL,NULL,SW_SHOW);

Q: 如何启动一个程序,直到它运行结束? SHELLEXECUTEINFO ShExecInfo = {0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = “c:\MyProgram.exe”; ShExecInfo.lpParameters = “”; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo;); WaitForSingleObject(ShExecInfo.hProcess,INFINITE); 或: PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; //This is an [in] parameter ZeroMemory(&StartupInfo;, sizeof(StartupInfo)); StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field if(CreateProcess(“c:\winnt\notepad.exe”, NULL, NULL,NULL,FALSE,0,NULL, NULL,&StartupInfo;,&ProcessInfo;)) { WaitForSingleObject(ProcessInfo.hProcess,INFINITE); CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); } else { MessageBox(“The process could not be started…”); }

Q: 如何显示文件或文件夹的属性? SHELLEXECUTEINFO ShExecInfo ={0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST ; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = “properties”; ShExecInfo.lpFile = “c:\“; //can be a file as well ShExecInfo.lpParameters = “”; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo;);

程序热键的实现

发表于 2005-01-19 | 分类于 技术控 | | 阅读次数:
字数统计: 437 字 | 阅读时长 ≈ 1 分钟

[问题提出] 有的程序需要自定义组合键完成一定功能,如何实现?

[解决方法] RegisterHotKey函数原型及说明: BOOL RegisterHotKey( HWND hWnd, // 接收WM_HOTKEY的窗口句柄 int id, // hot key的ID号. UINT fsModifiers, // 响应那个热键. UINT vk // 与热键配合的键.

其中:
    1)id的说明:
    id为你自己定义的一个ID值,对一个线程来讲其值必需在0x0000  -  0xBFFF范围之内,对DLL来讲其值必需在0xC000  -  0xFFFF  范围之内,在同一进程内该值必须唯一

    2)fsModifiers的取值如下:
        .MOD_ALT
        .MOD_CONTROL
        .MOD_SHIFT
        .MOD_WIN

[程序实现] 建立名为My的对话框工程.本例要用到RegisterHotKey()实现Alt+D的快捷键组合功能.在调用该函数后你的进程会在ALT+D按下时比系统先得到通知.你需要处理的消息是WM_HOTKEY. 如下:

在MyDlg.h中:
class  CMyDlg  :  public  CDialog
{
          //  Construction
          public:
                  int  m_nHotKeyID;//为你自己定义的一个hot  key的ID值,在整个程序唯一.
          ........
          protected:
                  HICON  m_hIcon;

          //  Generated  message  map  functions
          //{AFX_MSG(CMyDlg)
          virtual  BOOL  OnInitDialog();
          afx_msg  void  OnSysCommand(UINT  nID,  LPARAM  lParam);
          afx_msg  void  OnPaint();
          afx_msg  HCURSOR  OnQueryDragIcon();
          afx_msg  LONG  OnHotKey(WPARAM  wParam,LPARAM  lParam);//手动加入.
          //}AFX_MSG
          DECLARE_MESSAGE_MAP()
};

在MyDlg.cpp中:
#define  VK_D  68

..............
BEGIN_MESSAGE_MAP(CMyDlg,  CDialog)
          //{AFX_MSG_MAP(CHotKey1Dlg)
          ON_WM_SYSCOMMAND()
          ON_WM_PAINT()
          ON_WM_QUERYDRAGICON()
          ON_BN_CLICKED(IDOK,  OnRegisterHotKey)
          ON_BN_CLICKED(IDCANCEL,  OnUnregisterHotKey)
          ON_MESSAGE(WM_HOTKEY,OnHotKey)                                          //手动加入.
          //}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL  CMyDlg::OnInitDialog()
{
          CDialog::OnInitDialog();

          //  Add  "About..."  menu  item  to  system  menu.
          m_nHotKeyID=0;
          BOOL  m_isKeyRegistered  =  RegisterHotKey(GetSafeHwnd(),m_nHotKeyID,MOD_ALT,VK_D);
          ASSERT(m_isKeyRegistered  !=  FALSE);
          return  TRUE;    //  return  TRUE    unless  you  set  the  focus  to  a  control
}

在取消按钮的事件函数中加入:
void  CMyDlg::OnCancel()
{
          BOOL  m_iskeyUnregistered  =  UnregisterHotKey(GetSafeHwnd(),  m_nHotKeyID);
          ASSERT(m_iskeyUnregistered  !=  FALSE);
          CDialog::OnCancel();
}

处理截到的组合键,并处理:
LONG  CMyDlg::OnHotKey(WPARAM  wParam,LPARAM  lParam)
{
          AfxMessageBox("你按下了组合键:Alt+D");
          //加入相关代码.
          return  0;
}

大家试试此功能,希望有不对之处给以指正.

开机自动运行

发表于 2005-01-16 | 分类于 技术控 | | 阅读次数:
字数统计: 106 字 | 阅读时长 ≈ 1 分钟

BOOL SetAutoRun(CString strPath)//开机自动运行 { CString str; HKEY hRegKey; BOOL bResult; str=_T(“Software\Microsoft\Windows\CurrentVersion\Run”); if(RegOpenKey(HKEY_LOCAL_MACHINE, str, &hRegKey;) != ERROR_SUCCESS) bResult=FALSE; else { _splitpath(strPath.GetBuffer(0),NULL,NULL,str.GetBufferSetLength(MAX_PATH+1),NULL); strPath.ReleaseBuffer(); str.ReleaseBuffer(); if(::RegSetValueEx( hRegKey, str, 0, REG_SZ, (CONST BYTE *)strPath.GetBuffer(0), strPath.GetLength() ) != ERROR_SUCCESS) bResult=FALSE; else bResult=TRUE; strPath.ReleaseBuffer(); } return bResult; }

其中strPath参数表示要设置为自运行的程序的绝对路径。当设置成功时返回true,否则返回false。
1…414243…48
Timothy

Timothy

Timothy的技术博客,记录技术以及生活点滴

566 日志
8 分类
1187 标签
RSS
github twitter
Links
  • ZWWoOoOo
  • 花開未央
  • 守望轩
  • 大漠说程序
  • ChengBo
  • BlueAndHack
  • 程序员小辉
  • 子痕的博客
  • WoodenRobot
  • VPS大佬
  • 毕扬博客
  • VPSDad
  • 猫爪导航
  • ss1271的奋斗
  • Kian.Li
  • YoungForest
  • Fred's Blog
  • Jacklandrin
© 2025 Timothy
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4