青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

面對現實,超越自己
逆水行舟,不進則退
posts - 269,comments - 32,trackbacks - 0

添加消息響應WM_CTLCOLOR,
Static代碼如下:

HBRUSH CTest1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
HBRUSH hbr 
= CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
CFont m_font;   //聲明變量
m_font.CreatePointFont(600,"華文行楷"); //設置字體大小和類型
if(pWnd->GetDlgCtrlID()==IDC_STATIC01)//可以用CTLCOLOR_STATIC表示靜態控件
{
   pDC
->SelectObject(&m_font);       //設置字體 
   pDC->SetTextColor(RGB(0,0,255)); //設置字體顏色
   pDC->SetBkMode(TRANSPARENT);      //屬性設置為透明
   return (HBRUSH)::GetStockObject(NULL_BRUSH); //不返回畫刷
}
// TODO: Return a different brush if the default is not desired
return hbr;
}

Radio和Check代碼如下
HBRUSH CLoginDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    //HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    HBRUSH hbr = ::CreateSolidBrush(#f9f9f9);

    // TODO:  Change any attributes of the DC here

    if (pWnd->GetDlgCtrlID() == IDC_RADIO_REALNAME  ||
        pWnd->GetDlgCtrlID() == IDC_RADIO_ANONYMOUS ||
        pWnd->GetDlgCtrlID() == IDC_CHECK_SELFSELECT)
    {
        pDC->SetBkMode(TRANSPARENT);

        CRect rc;
        pWnd->GetWindowRect(&rc);
        ScreenToClient(&rc);

        CDC* dc = GetDC();
        pDC->BitBlt(0,0,rc.Width(),rc.Height(),dc,rc.left,rc.top,SRCCOPY);    //把父窗口背景先畫到按鈕上
        ReleaseDC(dc);

        hbr = (HBRUSH) ::GetStockObject(NULL_BRUSH);
    }
}

 

posted @ 2013-08-18 16:54 王海光 閱讀(11328) | 評論 (0)編輯 收藏

       采用TCP連接的C/S模式軟件,連接的雙方在連接空閑狀態時,如果任意一方意外崩潰、當機、網線斷開或路由器故障,另一方無法得知TCP連接已經失效,除非繼續在此連接上發送數據導致錯誤返回。很多時候,這不是我們需要的。我們希望服務器端和客戶端都能及時有效地檢測到連接失效,然后優雅地完成一些清理工作并把錯誤報告給用戶。
      如何及時有效地檢測到一方的非正常斷開,一直有兩種技術可以運用。一種是由TCP協議層實現的Keepalive,另一種是由應用層自己實現的心跳包
      TCP默認并不開啟Keepalive功能,因為開啟Keepalive功能需要消耗額外的寬帶和流量,盡管這微不足道,但在按流量計費的環境下增加了費用,另一方面,Keepalive設置不合理時可能會因為短暫的網絡波動而斷開健康的TCP連接。并且,默認的Keepalive超時需要7,200,000 milliseconds,即2小時,探測次數為5次。
      對于Win2K/XP/2003,可以從下面的注冊表項找到影響整個系統所有連接的keepalive參數:
       [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters]
        "KeepAliveTime”=dword:006ddd00
        "KeepAliveInterval"=dword:000003e8 
        "MaxDataRetries"="5"

      對于實用的程序來說,2小時的空閑時間太長。因此,我們需要手工開啟Keepalive功能并設置合理的Keepalive參數。

// 開啟KeepAlive
BOOL bKeepAlive = TRUE;
int nRet = ::setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(bKeepAlive));

if (nRet == SOCKET_ERROR)
{
return FALSE;
}


// 設置KeepAlive參數
tcp_keepalive alive_in = {0};
tcp_keepalive alive_out 
= {0};
alive_in.keepalivetime 
= 5000// 開始首次KeepAlive探測前的TCP空閉時間

alive_in.keepaliveinterval 
= 1000// 兩次KeepAlive探測間的時間間隔

alive_in.onoff 
= TRUE;
unsigned 
long ulBytesReturn = 0;

nRet 
= WSAIoctl(socket_handle, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in),
&alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);
if (nRet == SOCKET_ERROR)
{
return FALSE;


}



開啟Keepalive選項之后,對于使用IOCP模型的服務器端程序來說,一旦檢測到連接斷開,GetQueuedCompletionStatus函數將立即返回FALSE,使得服務器端能及時清除該連接、釋放該連接相關的資源。對于使用select模型的客戶端來說,連接斷開被探測到時,以recv目的阻塞在socket上的select方法將立即返回SOCKET_ERROR,從而得知連接已失效,客戶端程序便有機會及時執行清除工作、提醒用戶或重新連接。

 

另一種技術,由應用程序自己發送心跳包來檢測連接的健康性。客戶端可以在一個Timer中或低級別的線程中定時向發服務器發送一個短小精悍的包,并等待服務器的回應。客戶端程序在一定時間內沒有收到服務器回應即認為連接不可用,同樣,服務器在一定時間內沒有收到客戶端的心跳包則認為客戶端已經掉線。

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 windows下此處的”非正常斷開”指TCP連接不是以優雅的方式斷開,如網線故障等物理鏈路的原因,還有突然主機斷電等原因.

有兩種方法可以檢測:

1.TCP連接雙方定時發握手消息

 


2.利用TCP協議棧中的KeepAlive探測
第二種方法簡單可靠,只需對TCP連接兩個Socket設定KeepAlive探測,
所以本文只講第二種方法在Linux,Window2000下的實現(在其它的平臺上沒有作進一步的測試)


Windows 2000平臺下 頭文件
#include 
<mstcpip.h>
//定義結構及宏
/*

struct TCP_KEEPALIVE {
u_longonoff;
u_longkeepalivetime;
u_longkeepaliveinterval;
}
 ;
*/

    tcp_keepalive live,liveout;  
    live.keepaliveinterval=5000; //每5秒發一次探測報文,發5次沒有回應,就斷開
    live.keepalivetime=30000;//超過30s沒有數據,就發送控測包
    
    live.onoff=TRUE;  
    int Opt = 1;
    int iRet = setsockopt(Accept,SOL_SOCKET,SO_KEEPALIVE,(char *)&Opt,sizeof(int));  
    if(iRet == 0)
    {
         DWORD dw;
         if(::WSAIoctl(Accept,SIO_KEEPALIVE_VALS,
          &live,sizeof(live),&liveout,sizeof(liveout),
          &dw,NULL,NULL)== SOCKET_ERROR){
     }  
}


ACE下代碼 //by rainfish blog.csdn.net/bat603

 

int Opt = 1;
//在測試過程中,發現檢測的次數是5次,即下面的設置中,從最近一次消息開始計算的10秒后,每次間隔5秒,連續發送5次,即35秒發現網絡斷了
tcp_keepalive live,liveout; 
live.keepaliveinterval=5000//每次檢測的間隔 (單位毫秒)
live.keepalivetime=10000//第一次開始發送的時間(單位毫秒)
live.onoff=TRUE; 
int iRet = stream.set_option(SOL_SOCKET,SO_KEEPALIVE,&Opt,sizeof(int)); 
if(iRet == 0)

      DWORD dw;
      //此處顯示了在ACE下獲取套接字的方法,即句柄的(SOCKET)化就是句柄
      if(WSAIoctl((SOCKET)h,SIO_KEEPALIVE_VALS,&live,sizeof(live),
      &liveout,sizeof(liveout),&dw,NULL,NULL)== SOCKET_ERROR)
      {
            //Delete Client 
            return
      
}

 


Linux平臺下

#include "/usr/include/linux/tcp.h"
#include "/usr/include/linux/socket.h"
////KeepAlive實現,單位秒
//下面代碼要求有ACE,如果沒有包含ACE,則請把用到的ACE函數改成linux相應的接口
int keepAlive = 1;//設定KeepAlive
int keepIdle = 5;//開始首次KeepAlive探測前的TCP空閉時間
int keepInterval = 5;//兩次KeepAlive探測間的時間間隔
int keepCount = 3;//判定斷開前的KeepAlive探測次數
if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1)
{
      ACE_DEBUG ((LM_INFO,
      ACE_TEXT ("(%P|%t) setsockopt SO_KEEPALIVE error!/n")));
}
if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle)) == -1)
{
      ACE_DEBUG ((LM_INFO,
      ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPIDLE error!/n")));
}
if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval)) == -1)
{
      ACE_DEBUG ((LM_INFO,
      ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPINTVL error!/n")));
}
if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount)) == -1)
{
      ACE_DEBUG ((LM_INFO,
      ACE_TEXT ("(%P|%t)setsockopt TCP_KEEPCNT error!/n")));
}

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


本文轉自:http://m.shnenglu.com/API/archive/2013/08/13/202516.html

 

posted @ 2013-08-14 19:14 王海光 閱讀(1248) | 評論 (0)編輯 收藏
API:
要取得屏幕大小,可以用下面幾個函數:
int  cx   =  GetSystemMetricsSM_CXFULLSCREEN );
int  cy   =  GetSystemMetricsSM_CYFULLSCREEN );
通過上邊兩個函數獲取的是 顯示屏幕的大小,但不包括任務欄等區域

int  cx   =   GetSystemMetrics(   SM_CXSCREEN   );   
int  cy   =   GetSystemMetrics(   SM_CYSCREEN   );
這兩個函數獲取的是真正屏幕的大小。

MFC:
HDC hDC =  ::GetDC(HWND(NULL));               // 得到屏幕DC  
int x  =  ::GetDeviceCaps(hDC,HORZRES);       // 寬  
int y  =  ::GetDeviceCaps(hDC,VERTRES);        // 高   
::ReleaseDC(HWND(NULL),hDC);                  // 釋放DC
posted @ 2013-08-13 14:09 王海光 閱讀(6484) | 評論 (0)編輯 收藏
MFC程序vs2008編譯通過,運行時出錯,無法打開,提示f:\dd\xxxx的docsingl.cpp中的210行,找到以下代碼:
void CSingleDocTemplate::SetDefaultTitle(CDocument* pDocument)
{
        CString strDocName;
        if (!GetDocString(strDocName, CDocTemplate::docName) ||
             strDocName.IsEmpty())
        {
                // use generic 'untitled'
                ENSURE(strDocName.LoadString(AFX_IDS_UNTITLED));
        }
     pDocument->SetTitle(strDocName);
}

紅色行就是出錯地方,原因是資源文件引起,一般是從英文或其它語言改成簡體中文而造成,把語言相關改為以下幾行
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE 4, 2
#pragma code_page(936)
#endif //_WIN32
posted @ 2013-08-12 17:41 王海光 閱讀(1288) | 評論 (0)編輯 收藏
Linux下的段錯誤產生的原因及調試方法

   原文地址:http://www.upsdn.net/html/2006-11/775.html 
   參考地址:http://www.cnblogs.com/khler/archive/2010/09/16/1828349.html 

簡而言之,產生段錯誤就是訪問了錯誤的內存段,一般是你沒有權限,或者根本就不存在對應的物理內存,尤其常見的是訪問0地址.

一般來說,段錯誤就是指訪問的內存超出了系統所給這個程序的內存空間,通常這個值是由gdtr來保存的,他是一個48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相應于gdt的下標,最后3位包括了程序是否在內存中以及程序的在cpu中的運行級別,指向的gdt是由以64位為一個單位的表,在這張表中就保存著程序運行的代碼段以及數據段的起始地址以及與此相應的段限和頁面交換還有程序運行級別還有內存粒度等等的信息。一旦一個程序發生了越界訪問,cpu就會產生相應的異常保護,于是segmentation fault就出現了.

在編程中以下幾類做法容易導致段錯誤,基本是是錯誤地使用指針引起的

1)訪問系統數據區,尤其是往  系統保護的內存地址寫數據
   最常見就是給一個指針以0地址
2)內存越界(數組越界,變量類型不一致等) 訪問到不屬于你的內存區域

解決方法

我們在用C/C++語言寫程序的時侯,內存管理的絕大部分工作都是需要我們來做的。實際上,內存管理是一個比較繁瑣的工作,無論你多高明,經驗多豐富,難 免會在此處犯些小錯誤,而通常這些錯誤又是那么的淺顯而易于消除。但是手工“除蟲”(debug),往往是效率低下且讓人厭煩的,本文將就"段錯誤"這個 內存訪問越界的錯誤談談如何快速定位這些"段錯誤"的語句。
下面將就以下的一個存在段錯誤的程序介紹幾種調試方法:
     1  dummy_function (void)
     2  {
     3          unsigned char *ptr = 0x00;
     4          *ptr = 0x00;
     5  }
     6
     7  int main (void)
     8  {
     9          dummy_function ();
    10
    11          return 0;
    12  }
作為一個熟練的C/C++程序員,以上代碼的bug應該是很清楚的,因為它嘗試操作地址為0的內存區域,而這個內存區域通常是不可訪問的禁區,當然就會出錯了。我們嘗試編譯運行它:
xiaosuo@gentux test $ ./a.out
段錯誤
果然不出所料,它出錯并退出了。
1.利用gdb逐步查找段錯誤:
這種方法也是被大眾所熟知并廣泛采用的方法,首先我們需要一個帶有調試信息的可執行程序,所以我們加上“-g -rdynamic"的參數進行編譯,然后用gdb調試運行這個新編譯的程序,具體步驟如下:
xiaosuo@gentux test $ gcc -g -rdynamic d.c
xiaosuo@gentux test $ gdb ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) r
Starting program: /home/xiaosuo/test/a.out

Program received signal SIGSEGV, Segmentation fault.
0x08048524 in dummy_function () at d.c:4
4               *ptr = 0x00;
(gdb)                       
哦?!好像不用一步步調試我們就找到了出錯位置d.c文件的第4行,其實就是如此的簡單。
從這里我們還發現進程是由于收到了SIGSEGV信號而結束的。通過進一步的查閱文檔(man 7 signal),我們知道SIGSEGV默認handler的動作是打印”段錯誤"的出錯信息,并產生Core文件,由此我們又產生了方法二。
2.分析Core文件:
Core文件是什么呢?
The  default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process's memory  at the time of termination.  A list of the signals which cause a process to dump core can be found in signal(7).
以 上資料摘自man page(man 5 core)。不過奇怪了,我的系統上并沒有找到core文件。后來,憶起為了漸少系統上的拉圾文件的數量(本人有些潔癖,這也是我喜歡Gentoo的原因 之一),禁止了core文件的生成,查看了以下果真如此,將系統的core文件的大小限制在512K大小,再試:
xiaosuo@gentux test $ ulimit -c
0
xiaosuo@gentux test $ ulimit -c 1000
xiaosuo@gentux test $ ulimit -c
1000
xiaosuo@gentux test $ ./a.out
段錯誤 (core dumped)
xiaosuo@gentux test $ ls
a.out  core  d.c  f.c  g.c  pango.c  test_iconv.c  test_regex.c
core文件終于產生了,用gdb調試一下看看吧:
xiaosuo@gentux test $ gdb ./a.out core
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".


warning: Can't read pathname for load map: 輸入/輸出錯誤.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0  0x08048524 in dummy_function () at d.c:4
4               *ptr = 0x00;
哇,好歷害,還是一步就定位到了錯誤所在地,佩服一下Linux/Unix系統的此類設計。
接著考慮下去,以前用windows系統下的ie的時侯,有時打開某些網頁,會出現“運行時錯誤”,這個時侯如果恰好你的機器上又裝有windows的編譯器的話,他會彈出來一個對話框,問你是否進行調試,如果你選擇是,編譯器將被打開,并進入調試狀態,開始調試。
Linux下如何做到這些呢?我的大腦飛速地旋轉著,有了,讓它在SIGSEGV的handler中調用gdb,于是第三個方法又誕生了:
3.段錯誤時啟動調試:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

void dump(int signo)
{
        char buf[1024];
        char cmd[1024];
        FILE *fh;

        snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
        if(!(fh = fopen(buf, "r")))
                exit(0);
        if(!fgets(buf, sizeof(buf), fh))
                exit(0);
        fclose(fh);
        if(buf[strlen(buf) - 1] == '\n')
                buf[strlen(buf) - 1] = '\0';
        snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());
        system(cmd);

        exit(0);
}

        void
dummy_function (void)
{
        unsigned char *ptr = 0x00;
        *ptr = 0x00;
}

        int
main (void)
{
        signal(SIGSEGV, &dump);
        dummy_function ();

        return 0;
}
編譯運行效果如下:
xiaosuo@gentux test $ gcc -g -rdynamic f.c
xiaosuo@gentux test $ ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

Attaching to program: /home/xiaosuo/test/a.out, process 9563
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0  0xffffe410 in __kernel_vsyscall ()
#1  0xb7ee4b53 in waitpid () from /lib/libc.so.6
#2  0xb7e925c9 in strtold_l () from /lib/libc.so.6
#3  0x08048830 in dump (signo=11) at f.c:22
#4  <signal handler called>
#5  0x0804884c in dummy_function () at f.c:31
#6  0x08048886 in main () at f.c:38
怎么樣?是不是依舊很酷?
以上方法都是在系統上有gdb的前提下進行的,如果沒有呢?其實glibc為我們提供了此類能夠dump棧內容的函數簇,詳見/usr/include/execinfo.h(這些函數都沒有提供man page,難怪我們找不到),另外你也可以通過gnu的手冊進行學習。
4.利用backtrace和objdump進行分析:
重寫的代碼如下:
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

/* A dummy function to make the backtrace more interesting. */
        void
dummy_function (void)
{
        unsigned char *ptr = 0x00;
        *ptr = 0x00;
}

void dump(int signo)
{
        void *array[10];
        size_t size;
        char **strings;
        size_t i;

        size = backtrace (array, 10);
        strings = backtrace_symbols (array, size);

        printf ("Obtained %zd stack frames.\n", size);

        for (i = 0; i < size; i++)
                printf ("%s\n", strings[i]);

        free (strings);

        exit(0);
}

        int
main (void)
{
        signal(SIGSEGV, &dump);
        dummy_function ();

        return 0;
}
編譯運行結果如下:
xiaosuo@gentux test $ gcc -g -rdynamic g.c
xiaosuo@gentux test $ ./a.out
Obtained 5 stack frames.
./a.out(dump+0x19) [0x80486c2]
[0xffffe420]
./a.out(main+0x35) [0x804876f]
/lib/libc.so.6(__libc_start_main+0xe6) [0xb7e02866]
./a.out [0x8048601]
這次你可能有些失望,似乎沒能給出足夠的信息來標示錯誤,不急,先看看能分析出來什么吧,用objdump反匯編程序,找到地址0x804876f對應的代碼位置:
xiaosuo@gentux test $ objdump -d a.out

 8048765:       e8 02 fe ff ff          call   804856c <signal@plt>
 804876a:       e8 25 ff ff ff          call   8048694 <dummy_function>
 804876f:       b8 00 00 00 00          mov    $0x0,%eax
 8048774:       c9                      leave
我們還是找到了在哪個函數(dummy_function)中出錯的,信息已然不是很完整,不過有總比沒有好的啊!
后記:
本文給出了分析"段錯誤"的幾種方法,不要認為這是與孔乙己先生的"回"字四種寫法一樣的哦,因為每種方法都有其自身的適用范圍和適用環境,請酌情使用,或遵醫囑。

部分資料來源于xiaosuo @ cnblog.cn, 特此致謝

作者:upsdn整理   更新日期:2006-11-03
來源:upsdn.net   瀏覽次數: 



其它調試辦法

  • 添加日志 

            在Linux上的使用開源C++日志庫---log4cplus 



linux下追蹤函數調用堆棧

一般察看函數運行時堆棧的方法是使用GDB之類的外部調試器,但是,有些時候為了分析程序的BUG,(主要針對長時間運行程序的分析),在程序出錯時打印出函數的調用堆棧是非常有用的。

 在頭文件"execinfo.h"中聲明了三個函數用于獲取當前線程的函數調用堆棧

 Function: int backtrace(void **buffer,int size)

 該函數用與獲取當前線程的調用堆棧,獲取的信息將會被存放在buffer中,它是一個指針列表。參數 size 用來指定buffer中可以保存多少個void* 元素。函數返回值是實際獲取的指針個數,最大不超過size大小

 在buffer中的指針實際是從堆棧中獲取的返回地址,每一個堆棧框架有一個返回地址

 注意某些編譯器的優化選項對獲取正確的調用堆棧有干擾,另外內聯函數沒有堆棧框架;刪除框架指針也會使無法正確解析堆棧內容

 Function: char ** backtrace_symbols (void *const *buffer, int size)

 backtrace_symbols將從backtrace函數獲取的信息轉化為一個字符串數組. 參數buffer應該是從backtrace函數獲取的數組指針,size是該數組中的元素個數(backtrace的返回值)

 函數返回值是一個指向字符串數組的指針,它的大小同buffer相同.每個字符串包含了一個相對于buffer中對應元素的可打印信息.它包括函數名,函數的偏移地址,和實際的返回地址

 現在,只有使用ELF二進制格式的程序和苦衷才能獲取函數名稱和偏移地址.在其他系統,只有16進制的返回地址能被獲取.另外,你可能需要傳遞相應的標志給鏈接器,以能支持函數名功能(比如,在使用GNU ld的系統中,你需要傳遞(-rdynamic))

 該函數的返回值是通過malloc函數申請的空間,因此調用這必須使用free函數來釋放指針.

 注意:如果不能為字符串獲取足夠的空間函數的返回值將會為NULL

 Function:void backtrace_symbols_fd (void *const *buffer, int size, int fd)

 backtrace_symbols_fd與backtrace_symbols 函數具有相同的功能,不同的是它不會給調用者返回字符串數組,而是將結果寫入文件描述符為fd的文件中,每個函數對應一行.它不需要調用malloc函數,因此適用于有可能調用該函數會失敗的情況。

#include <execinfo.h> 
#include 
<stdio.h> 
#include 
<stdlib.h> 

/* Obtain a backtrace and print it to stdout. */ 
void print_trace (void

        
void *array[10]; 
        size_t size; 
        
char **strings; 
        size_t i; 

        size 
= backtrace (array, 10); 
        strings 
= backtrace_symbols (array, size); 

        printf (
"Obtained %zd stack frames.\n", size); 

        
for (i = 0; i < size; i++
                printf (
"%s\n", strings[i]); 

        free (strings); 


/* A dummy function to make the backtrace more interesting. */ 
void dummy_function (void

        print_trace (); 


int main (void

        dummy_function (); 
        
return 0
}
編譯運行的結果如下: 
# gcc bt.c -rdynamic -o bt 
# ./bt 
Obtained 5 stack frames.
./bt(_Z11print_tracev+0x19) [0x804870d]
./bt(_Z14dummy_functionv+0xb) [0x8048779]
./bt(main+0x16) [0x8048792]
/lib/libc.so.6(__libc_start_main+0xdc) [0x116e9c]
./bt(__gxx_personality_v0+0x31) [0x8048641]


注: addr2line - convert addresses into file names and line numbers.
posted @ 2013-07-31 12:07 王海光 閱讀(862) | 評論 (0)編輯 收藏

GetExitCodeThread函數是獲得線程的退出碼, 

函數: GetExitCodeThread()

功能:獲取一個結束線程的返回值

函數原形: BOOL GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode);

參數: hThread 指向欲獲取返回值的線程對象的句柄

               lpExitCode 用于存儲線程的返回值

返回值:函數執行成功則返回非0值,否則返回 0FALSE

第一個參數是線程句柄,用 CreateThread 創建線程時獲得到。

第二個參數是一個 DWORD的指針,用戶應該使用一個 DWORD 類型的變量去接收數據,返回的數據是線程的退出碼,
通過線程退出碼可以判斷線程是否正在運行,還是已經退出。或者可以判斷線程是否是正常退出還是異常退出。

執行成功時,存放線程的狀態碼,如果是線程的返回值,表示線程執行完,  如果線程沒執行完,返回STILL_ACTIVE,如果線程的返回值就是STILL_ACTIVE,就無法判斷  .


MSDN解釋:

GetExitCodeThread Function

Retrieves the termination status of the specified thread.

 

BOOL WINAPI GetExitCodeThread(   __in           HANDLE hThread,    __out         LPDWORD lpExitCode ); 

Parameters

hThread

A handle to the thread.

The handle must have the THREAD_QUERY_INFORMATION access right. For more information, see Thread Security and Access Rights.

lpExitCode

A pointer to a variable to receive the thread termination status. If the specified thread has not terminated and the function succeeds, the termination status returned is STILL_ACTIVE.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

If the thread has terminated and the function succeeds, the termination status returned may be one of the following:

 

  • The exit value specified in the ExitThread or TerminateThread function.
  • The return value from the thread function.
  • The exit value of the thread's process.

Warning  If a thread happens to return STILL_ACTIVE (259) as an error code, applications that test for this value could end up in an infinite loop.


參考例子:
 1 int main()     
 2 {         
 3     DWORD exitCode1 = 0;     
 4     DWORD exitCode2 = 0;     
 5     DWORD threadId;          
 6   
 7     HANDLE hThrd1 = CreateThread(NULL, 0,   ThreadFunc1, 0, 0, &threadId );  
 9     if (hThrd1)     
10         printf("Thread 1 launched\n");    
11 
13     HANDLE hThrd2 = CreateThread(NULL, 0,  ThreadFunc2, 0, 0, &threadId );     
14     if (hThrd2)     
15         printf("Thread 2 launched\n");    
16 
18     for (;;)      
19     {   
20           printf("Press any key to exit..\n");   
21           getch();   
22           GetExitCodeThread(hThrd1, &exitCode1);   
23           GetExitCodeThread(hThrd2, &exitCode2);   
24           if ( exitCode1 == STILL_ACTIVE )   
25               puts("Thread 1 is still running!");   
26   
27           if ( exitCode2 == STILL_ACTIVE )   
28               puts("Thread 2 is still running!");   
29           if ( exitCode1 != STILL_ACTIVE   && exitCode2 != STILL_ACTIVE )   
30               break;   
31     }   
32   
33     CloseHandle(hThrd1);   
34     CloseHandle(hThrd2);   
35    
36     printf("Thread 1 returned %d\n", exitCode1);   
37     printf("Thread 2 returned %d\n", exitCode2);   
38     return EXIT_SUCCESS;     
39 }    
40   
41 DWORD WINAPI ThreadFunc1(LPVOID n)   
42 {   
43      Sleep((DWORD)n*1000*2);   
44      return (DWORD)n * 10;   
45 } 
46 
48 DWORD WINAPI ThreadFunc2(LPVOID n)   
49 {   
50      Sleep((DWORD)n*1000*2);   
51      return (DWORD)n * 10;   
52 } 
posted @ 2013-07-31 11:37 王海光 閱讀(5866) | 評論 (0)編輯 收藏

以上是源碼及演示程序下載地址

(文章原地址 http://www.codeproject.com/Articles/24969/An-MFC-picture-control-to-dynamically-show-picture

Introduction 介紹

這篇文章描述的是一個可以用于在對話框上顯示各種主流類型圖片 (如 BMP, GIF, JPEG...) MFC控件

Background 背景

我花了一些時間去搜索可以用于顯示圖片的MFC控件, 但卻沒有發現合適的。 所以我決定自己做一個輕量級,靈活度高的圖片控件(Picture control)去顯示各種類型的圖片。

Using the code 如何使用

這個控件內部使用的是GDI+庫,所以請在使用時把GdiPlus.lib加入到你的工程中(include libraries)。

使用這個控件時,先用VC++對話框設計器創建一個靜態文字控件(static text control 。之后用MFC向導為這個控件分配一個控件變量,類型定義為CPictureCtrl。

現在你可以用你的控件裝載顯示圖片了,你只需要在這幾個CPictureCtrl::LoadFrom... 函數, 選擇合適你需要的的進行調用。裝載后控件會自動更新并顯示圖片。

要清除掉控件中顯示的圖片,調用CPictureCtrl::FreeImage即可。

你的圖片會被自動調整到控件的大小,這可能會改變圖片原先的長寬比例。

 Collapse | Copy Code
class CPictureCtrl :     
public CStatic
{
public:
   //Constructor
   CPictureCtrl(void);
   //Destructor
   ~CPictureCtrl(void);

public:
   //Loads an image from a file
   BOOL LoadFromFile(CString &szFilePath);
   //Loads an image from an IStream interface
   BOOL LoadFromStream(IStream* piStream);
   //Loads an image from a byte stream;
   BOOL LoadFromStream(BYTE* pData, size_t nSize);
   //Loads an image from a Resource
   // BOOL LoadFromResource(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType);
   //Overload - Single load function
   BOOL Load(CString &szFilePath);
   BOOL Load(IStream* piStream);
   BOOL Load(BYTE* pData, size_t nSize);
   // BOOL Load(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType);
   //Frees the image data
   void FreeData();

protected:
   virtual void PreSubclassWindow();
   //Draws the Control
   virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
   virtual BOOL OnEraseBkgnd(CDC* pDC);

private:
   //Internal image stream buffer
   IStream* m_pStream;
   //Control flag if a pic is loaded
   BOOL m_bIsPicLoaded;
   //GDI Plus Token
   ULONG_PTR m_gdiplusToken; };

Points of interest

這個控件是基于 CStatic control 設計的(基類使用的是CStatic)。所以你可以使用CStatic control的各種功能,但它并不會顯示任何文字。對GDI+庫的使用使其可以支持各種主流類型的圖片。

History 歷史

  • 1.0 - Initial release.
  • 1.1 - A bug when drawing the control without a loaded image was corrected.
  • 1.2 - A bug when drawing the control was corrected.

    Loading an image from a resource is disabled due to problems recognizing it correctly as an image.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

TEiseler

Tester / Quality Assurance

Germany Germany

Member
 

本文轉自:http://blog.csdn.net/cashey1991/article/details/7516996
posted @ 2013-07-22 18:09 王海光 閱讀(2233) | 評論 (0)編輯 收藏
重載 DrawItem 函數或Onpaint函數
void CListCtrlCl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    // 重繪網格線 [7/12/2013 dell]
    const MSG *msg = GetCurrentMessage();
    DefWindowProc( msg->message, msg->wParam, msg->lParam );

    // Draw the lines only for LVS_REPORT mode
    if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
    {
        // Get the number of columns
        CClientDC dc(this );
        CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
        int nColumnCount = pHeader->GetItemCount();

        // The bottom of the header corresponds to the top of the line 
        RECT rect, rectCol;
        pHeader->GetClientRect( &rect );
        int top = rect.bottom;

        // Now get the client rect so we know the line length and
        
// when to stop
        GetClientRect( &rect );

        if( !GetItemRect( 1, &rectCol, LVIR_BOUNDS ))
            return;

        int height1 = rectCol.bottom - rectCol.top;

        // The border of the column is offset by the horz scroll
        int borderx = 0 - GetScrollPos( SB_HORZ );
        forint i = 0; i < nColumnCount; i++ )
        {
            // Get the next border
            borderx += GetColumnWidth( i );

            // if next border is outside client area, break out
            if( borderx >= rect.right ) break;

            // Draw the line.
            dc.MoveTo( borderx-1, top/*top*/);
            dc.LineTo( borderx-1, (2+lpDrawItemStruct->itemID)*height1/*rect.bottom*/ );
        }

        // Draw the horizontal grid lines

        
// First get the height
        if( !GetItemRect( 0, &rect, LVIR_BOUNDS ))
            return;

        int height = rect.bottom - rect.top;

        GetClientRect( &rect );
        int width = rect.right;

        for(int i = 1; i <= lpDrawItemStruct->itemID+1; i++ )
        {
            dc.MoveTo( 0, top + height*i);
            dc.LineTo( width, top + height*i );
        }
    }
}

本文轉自:http://www.codeguru.com/cpp/controls/listview/gridlines/article.php/c963/Drawing-horizontal-and-vertical-gridlines.htm
posted @ 2013-07-12 11:10 王海光 閱讀(2672) | 評論 (0)編輯 收藏
示例代碼:
Sock_UDP::Sock_UDP()
{
    m_socket = INVALID_SOCKET;

    WSAData ws; 

    //每個Winsock程序必須使用WSAStartup載入合適的Winsock動態鏈接庫,如果載入失敗,WSAStartup將返回SOCKET_ERROR,這個錯誤就是WSANOTINITIALISED
    if (WSAStartup(MAKEWORD(2,2),&ws)!=0)
    {
        LOG("WSAStartup failed! Error: %d", WSAGetLastError());
    }
}

Sock_UDP::~Sock_UDP()
{
}
/******************************************************************
* 函數介紹:對連接進行初始化
* 輸入參數: strIPAddress:廣播的ip地址,strPort: 端口號
* 輸出參數:
* 返回值  :
******************************************************************
*/
BOOL Sock_UDP::InitSocket(const CString strIPAddress,const CString strPort)
{    
    //創建套接字,ipv4,報文,udp協議
    m_socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

    //創建socket失敗
    if (INVALID_SOCKET == m_socket)
    {
        LOG("failed to create socket");

        return false;
    }

    //初始化sock地址
    InitSockAddress(strIPAddress,strPort);

    // 綁定
    if (bind (m_socket, 
        (struct sockaddr FAR *) &m_sockLocalAddress, 
        sizeof (m_sockLocalAddress)) == SOCKET_ERROR) 
    {
        //報錯        
        LOG("Binding socket failed! Error: %d" ,WSAGetLastError());
        closesocket (m_socket);

        return false;
    }

    int iOptVal=64; //1秒
    
// 設置組播存活時間
    if (setsockopt (m_socket, 
        IPPROTO_IP, 
        3, 
        (char FAR *)&iOptVal, 
        sizeof (int)) == SOCKET_ERROR)
    {
        //報錯
        LOG("setsockopt failed! Error: %d" ,WSAGetLastError());

        closesocket (m_socket);

        return false;
    }

    return true;
}

/******************************************************************
* 函數介紹:關閉socket
* 輸入參數:
* 輸出參數:
* 返回值  :
******************************************************************
*/
void Sock_UDP::CleanSocket()
{    
    shutdown(m_socket,0x01);

    closesocket(m_socket);
    WSACleanup();
}

/******************************************************************
* 函數介紹:初始化IP組播地址和端口
* 輸入參數:strIPAddress:ip地址,strPort: 端口號
* 輸出參數:
* 返回值  :
******************************************************************
*/
void Sock_UDP::InitSockAddress(const CString strIPAddress,const CString strPort)
{
    //本地sock地址設置
    m_sockLocalAddress.sin_family = AF_INET;     //ipv4地址類型
    m_sockLocalAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    m_sockLocalAddress.sin_port = htons(0);   
    memset(m_sockLocalAddress.sin_zero,0,8);

    //目的sock地址設置
    
//IPv4版本
    m_sockDesAddress.sin_family = AF_INET;
    //端口
    m_sockDesAddress.sin_port = htons (atol(strPort));  
    //地址
    m_sockDesAddress.sin_addr.s_addr = inet_addr (strIPAddress);

}

posted @ 2013-06-19 18:00 王海光 閱讀(6933) | 評論 (0)編輯 收藏

動態創建視圖時候 AfxCheckDialogTemplate執行出錯

mfcsdi架構中,準備多做幾個視圖,試圖類繼承自formview,但在動態創建視圖的時候出了錯誤,AfxCheckDialogTemplate執行出錯。后來通過搜索發現cformview類關聯對話框時候,資源必須具備child屬性。

1.CFormView類關聯的對話框資源必須具有Child屬性。

CFormView派生的類,可以關聯一個對話框資源。但該對話框資源必須在屬性設定中Style選定[Child]屬性,否則的話,
代碼可以編譯,但Debug運行會報告一個斷言錯誤,跟蹤代碼,斷言在:

#ifdef _DEBUG

    // dialog template must exist and be invisible with WS_CHILD set
    if (!_AfxCheckDialogTemplate(m_lpszTemplateName, TRUE))
    {
        ASSERT(FALSE);          // invalid dialog template name
        PostNcDestroy();        // cleanup if Create fails too soon
        return FALSE;
    }

#endif //_DEBUG

2.CFormView比較特殊,是一個父窗體嵌套了一個子窗體,所以,
CFormView類的派生類的實例不響應WM_CLOSE消息,僅僅響應WM_DESTROY消息。
另外,若要用代碼關閉當前View,也不能直接:PostMessage(WM_CLOSE,0,0);
而必須先獲取父窗體的指針,然后對父窗體發送WM_CLOSE消息才行,像這樣:
GetParent()-&gt;PostMessage(WM_CLOSE,0,0);
才能夠達到目的。
《深入淺出MFC》第八章461頁圖8-1清楚地說明了這種情況,View窗口是CChildFrame窗口的子窗口。

posted @ 2013-05-31 17:02 王海光 閱讀(2056) | 評論 (0)編輯 收藏
僅列出標題
共27頁: First 3 4 5 6 7 8 9 10 11 Last 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            今天的高清视频免费播放成人 | 午夜久久久久久久久久一区二区| 欧美成人国产| 欧美成人乱码一区二区三区| 免费的成人av| 亚洲激情中文1区| 亚洲狠狠丁香婷婷综合久久久| 国产主播精品在线| 亚洲福利小视频| aa级大片欧美| 亚洲欧美福利一区二区| 久久av一区二区三区| 男女激情视频一区| 亚洲美女av电影| 性欧美video另类hd性玩具| 久久综合久久综合久久综合| 欧美日韩一区二区三区在线看| 国产欧美一区二区精品性| 国产一区二区三区免费观看| 亚洲精品国精品久久99热一| 午夜精品视频在线观看一区二区| 老鸭窝91久久精品色噜噜导演| 亚洲高清不卡一区| 亚洲欧美第一页| 欧美高清你懂得| 国产亚洲精品久久久久婷婷瑜伽| 亚洲精品国产精品乱码不99按摩| 亚洲欧美99| 欧美激情精品久久久久| 亚洲一区在线免费| 欧美激情视频给我| 激情五月婷婷综合| 午夜视频一区二区| 亚洲精品一区二区三区四区高清| 欧美一区二区日韩一区二区| 欧美精品偷拍| 亚洲欧洲在线免费| 久久伊人精品天天| 亚洲欧美视频在线观看| 欧美日产一区二区三区在线观看| 好看的av在线不卡观看| 亚洲欧美高清| 日韩系列欧美系列| 欧美激情综合色综合啪啪| 国产精品自拍网站| 午夜精品久久久久久久久久久| 欧美激情综合色| 欧美一区三区二区在线观看| 欧美国产日韩一区| 久久久久www| 国产有码在线一区二区视频| 亚洲欧美成人一区二区在线电影| 欧美黄色免费网站| 久久综合精品一区| 亚洲高清视频在线观看| 久久先锋影音av| 久久福利影视| 伊人色综合久久天天| 可以看av的网站久久看| 久久精品视频99| 在线成人免费视频| 欧美激情视频在线播放 | 国产精品久久久久毛片大屁完整版| 亚洲日韩欧美视频一区| 亚洲高清一区二| 欧美激情在线| 一卡二卡3卡四卡高清精品视频| 亚洲国产天堂久久综合网| 欧美成人免费va影院高清| 亚洲精品一区二区在线观看| 亚洲黄色一区| 欧美日韩裸体免费视频| 一区二区三区高清| 亚洲一区日韩| 禁断一区二区三区在线| 欧美国产日本| 欧美日韩国产免费| 羞羞色国产精品| 欧美一区二区三区四区高清| 黄色成人在线观看| 你懂的国产精品| 欧美人成网站| 久久成人人人人精品欧| 久久先锋影音| 在线综合亚洲| 欧美专区中文字幕| 亚洲精品欧美日韩| 亚洲专区国产精品| 亚洲电影有码| 中文网丁香综合网| 在线精品亚洲一区二区| 99热在线精品观看| 国外视频精品毛片| 亚洲美女91| 黄色精品一区二区| 一区二区三区三区在线| 亚洲成人在线视频网站| 亚洲视频高清| 亚洲精品日韩激情在线电影 | 一区二区久久久久| 国模大胆一区二区三区| 亚洲欧洲一区| 狠狠久久亚洲欧美专区| 日韩一级在线观看| 亚洲国产欧美不卡在线观看| 亚洲一区美女视频在线观看免费| 亚洲黄色影片| 欧美在线观看一二区| 卡通动漫国产精品| 久久精品国产亚洲一区二区| 欧美日本亚洲| 老司机精品视频网站| 国产精品久久二区| 亚洲精品一区二区三区99| 在线电影国产精品| 欧美一级理论性理论a| 亚洲午夜日本在线观看| 欧美成人一区二区在线 | 亚洲免费影院| 一本色道久久综合亚洲精品婷婷 | 一本色道久久加勒比88综合| 在线观看视频亚洲| 午夜日韩福利| 午夜视频久久久| 国产精品mm| 99在线精品观看| 亚洲图片欧美午夜| 欧美日韩 国产精品| 亚洲国产婷婷香蕉久久久久久| 亚洲第一精品福利| 免费在线成人av| 亚洲成人在线视频播放| 国产视频在线观看一区二区三区 | 老司机精品导航| 黄色免费成人| 久久九九有精品国产23| 久久久久久黄| 黄网站色欧美视频| 久久婷婷国产综合精品青草| 久久久久一区二区三区四区| 国产偷国产偷精品高清尤物| 午夜视频久久久| 久久久久**毛片大全| 国产一区二区中文字幕免费看| 亚洲欧美在线磁力| 久久久免费精品| 狠狠色丁香婷婷综合| 久久三级福利| 最新国产拍偷乱拍精品| 中文欧美日韩| 国产麻豆精品在线观看| 久久精品视频导航| 欧美激情久久久久| 一区二区三区四区蜜桃| 国产精品五月天| 久久久久久久综合日本| 亚洲激情国产精品| 午夜在线一区| 在线欧美日韩国产| 欧美紧缚bdsm在线视频| 在线一区二区三区四区| 久久久成人精品| 亚洲日韩欧美视频一区| 国产精品国码视频| 久久一区二区三区四区五区| 亚洲日韩欧美一区二区在线| 亚洲欧美在线一区| 亚洲观看高清完整版在线观看| 欧美日韩精品高清| 久久国产毛片| 日韩一区二区精品葵司在线| 久久精彩免费视频| 欧美视频中文在线看| 欧美一级淫片aaaaaaa视频| 免费亚洲网站| 羞羞漫画18久久大片| 亚洲国产精品一区在线观看不卡| 欧美视频手机在线| 老司机精品福利视频| 亚洲综合精品四区| 亚洲人成精品久久久久| 久久国产精品免费一区| 99视频在线观看一区三区| 国产视频一区在线观看一区免费| 欧美激情视频给我| 久久精品国产96久久久香蕉| 一本久久知道综合久久| 欧美电影在线免费观看网站| 欧美一区二区三区四区夜夜大片| 91久久一区二区| 激情久久五月| 国产无一区二区| 国产精品第三页| 欧美日韩国产首页在线观看| 久久全球大尺度高清视频| 亚洲欧美日韩精品久久久| 一区二区激情小说| 99天天综合性| 日韩一级在线观看| 亚洲经典自拍|