小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Spy++原理初探

 9loong 2010-09-19
http://www./document/viewdoc/?id=1782
 

Spy++原理初探


作者:南京 宋陳三


下載源代碼

摘要:用Visual Studio搞開發(fā)的朋友對Spy++這個工具一定不陌生,它可以分析窗體結(jié)構(gòu)、進程和窗口消息,對開發(fā)工作有很大輔助作用。我們需要研究某個對象時,只要調(diào)出其查找窗口,拖動探測器的指針到指定窗口/控件上釋放即可。下面,筆者就和大家一起,用VC打造一個屬于自己的Spy++。

關(guān)鍵字:句柄 消息 子類化

正文:

  打開VC集成開發(fā)環(huán)境,建立一個基于對話框的工程。我們把這個工程取名為SpyXX。在窗體中畫上一個圖片框控件(Picture)、一個靜態(tài)文本控件(Static)、兩個復(fù)選框控件(Check Box)和一個選項卡控件(Tab Control)。界面設(shè)計如下圖。

  
  探測器的制作需要兩個圖標(biāo)文件(.ico)和一個鼠標(biāo)光標(biāo)文件(.cur),分別用于正常狀態(tài)下的顯示、鼠標(biāo)拖出時的顯示以及拖出時的鼠標(biāo)指針;這些資源哪里來啊?Spy++中就有啊,用eXeScope挖一下吧。(我是從其他軟件中挖出來的,名字好像叫超級什么霸,記不太清了,呵呵。)選項卡控件定義5個標(biāo)簽頁,分別為"常規(guī)"、"樣式"、"類"、"窗口"和"消息"。每個標(biāo)簽頁的內(nèi)容用一個屬性頁(Property Page)對話框來制作。下面,我們按照順序描述一下開發(fā)過程。
  

  一、探測器的制作
  探測器用一個圖片框控件來顯示,正常狀態(tài)下顯示一幅有靶的圖標(biāo)。當(dāng)鼠標(biāo)在上面按下時,顯示內(nèi)容立刻換為另一幅無靶的圖標(biāo),同時鼠標(biāo)指針變?yōu)榘袪睢_@樣,就給人一種靶心被拖出去的感覺了。通過上面的敘述,我們了解到圖片框需要響應(yīng)WM_LBUTTONDOWN消息和WM_LBUTTONUP消息。而圖片框在正常狀態(tài)下只響應(yīng)鼠標(biāo)單擊消息BN_CLICK。所以,我們要通過子類化來響應(yīng)上述兩個消息。
  把圖片框的ID設(shè)為IDC_PIC,并選中其Notify屬性(否則不響應(yīng)消息)。依次點擊菜單Insert->New Class,Class type選擇MFC Class,類名取為CMyPic,基類為CStatic。添加CSpyXXDlg類的私有成員變量CMyPic m_pic,在對話框的初始化過程中將其與圖片框關(guān)聯(lián)。代碼如下:

BOOL CSpyXXDlg::OnInitDialog()
            {
            CDialog::OnInitDialog();
            m_pic.SubclassDlgItem(IDC_PIC,this);
            ……
            return TRUE;
            }
  在CMyPic類中,我們就可以響應(yīng)鼠標(biāo)左鍵按下和彈起的消息了。按Ctrl + W打開Class Wizard,選擇Message Maps標(biāo)簽頁,在Class name下拉列表中選擇CMyPic。從Messages列表中分別增加WM_LBUTTONDOWN和WM_LBUTTONUP消息,并接受其缺省函數(shù)名OnLButtonDown和OnLButtonUp。圖標(biāo)交換和鼠標(biāo)光標(biāo)交換的代碼如下:
void CMyPic::OnLButtonDown(UINT nFlags, CPoint point)
            {
            // TODO: Add your message handler code here and/or call default
            SetCapture();   //鼠標(biāo)捕獲
            HCURSOR hc = LoadCursor(AfxGetApp()->m_hInstance, MAKEINTRESOURCE (IDC_CURSOR1));
            //IDC_CURSOR1是靶形光標(biāo)資源號
            ::SetCursor(hc);
            HICON hicon2 = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE (IDI_ICON2));
            //IDI_ICON2為無靶圖標(biāo)資源號
            this->SetIcon(hicon2);
            CStatic::OnLButtonDown(nFlags, point);
            }
            void CMyPic::OnLButtonUp(UINT nFlags, CPoint point)
            {
            // TODO: Add your message handler code here and/or call default
            ReleaseCapture(); //釋放鼠標(biāo)捕獲
            HICON hicon1 = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE (IDI_ICON1));
            //IDI_ICON1是有靶圖標(biāo)資源號
            this->SetIcon(hicon1);
            CStatic::OnLButtonUp(nFlags, point);
            }
  探測器外觀制作完成了??梢韵冗\行一下,把鼠標(biāo)按下后拖動試試。下面來實現(xiàn)其功能:獲取窗口句柄。根據(jù)鼠標(biāo)位置來確定窗口需要用到API函數(shù)GetCursorPos和WindowFromPoint。此外,我們還想做到像抓圖程序那樣,鼠標(biāo)移動到的地方,窗口四周會出現(xiàn)閃爍的矩形。這一點,我們用定時器來實現(xiàn)。定時器設(shè)在CSpyXXDlg類中,但要由CMyPic中的OnLButtonUp來啟動。所以,我們定義一個全局變量g_hMe將CSpyXXDlg的實例句柄保存起來。同時,被選取的窗口句柄也涉及到在多個標(biāo)簽頁中顯示,所以也用全局變量g_hWnd將之保存。其余的用于顯示標(biāo)簽頁的屬性頁對話框句柄分別用g_hPage0、g_hPage1、g_hPage2、g_hPage3和g_hPage4來保存。啟動定時器的代碼如下:
FromHandle(g_hMe)->SetTimer(1,600,NULL);
  在定時器中,我們要實現(xiàn)桌面范圍內(nèi)的矩形繪制。代碼如下:
POINT pnt;
            RECT rc;
            HWND DeskHwnd = ::GetDesktopWindow(); //取得桌面句柄
            HDC DeskDC = ::GetWindowDC(DeskHwnd); //取得桌面設(shè)備場景
            int oldRop2 = SetROP2(DeskDC, R2_NOTXORPEN);
            ::GetCursorPos(&pnt); //取得鼠標(biāo)坐標(biāo)
            HWND UnHwnd = ::WindowFromPoint(pnt) ; //取得鼠標(biāo)指針處窗口句柄
            g_hWnd=UnHwnd;
            ::GetWindowRect(g_hWnd, &rc); //獲得窗口矩形
            if( rc.left < 0 ) rc.left = 0;
            if (rc.top < 0 ) rc.top = 0;
            HPEN newPen = ::CreatePen(0, 3, 0); //建立新畫筆,載入DeskDC
            HGDIOBJ oldPen = ::SelectObject(DeskDC, newPen);
            ::Rectangle(DeskDC, rc.left, rc.top, rc.right, rc.bottom); //在窗口周圍顯示閃爍矩形
            Sleep(400); //設(shè)置閃爍時間間隔
            ::Rectangle( DeskDC, rc.left, rc.top, rc.right, rc.bottom);
            ::SetROP2(DeskDC, oldRop2);
            ::SelectObject( DeskDC, oldPen);
            ::DeleteObject(newPen);
            ::ReleaseDC( DeskHwnd, DeskDC);
            DeskDC = NULL;
  到此,探測器功能全部完成。

  二、兩個復(fù)選框
  第一個復(fù)選框是"總在最上面",代碼如下:

void CSpyXXDlg::OnChktop()
            {
            int nTop=((CButton*)GetDlgItem(IDC_CHKTOP))->GetCheck();
            if(nTop==1)
            :: SetWindowPos(m_hWnd,HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
            else
            ::SetWindowPos(m_hWnd,HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
            }
  第二個復(fù)選框是"16進制"。因為其值影響到多個屬性頁對話框的內(nèi)容,所以,也用一全局變量g_nHex保存之:
void CSpyXXDlg::OnChkhex()
            {
            g_nHex=((CButton*)GetDlgItem(IDC_CHKHEX))->GetCheck();
            }
  這里,我們還建立了一個全局函數(shù)Display,來輸出16進制和10進制時的句柄值:
CString Display(int nVal)
            {
            CString str;
            if(g_nHex==1)
            {
            str.Format("%x",nVal);
            str.MakeUpper();
            }
            else
            str.Format("%d",nVal);
            return str;
            }
  三、選項卡控件
  選項卡控件中,5個標(biāo)簽頁對應(yīng)5個屬性頁對話框,與它們關(guān)聯(lián)的類分別取名為CPage0、CPage1、CPage2、CPage3、CPage4。在CSpyXXDlg中建立私有成員變量m_page0、m_page1、m_page2、m_page3、m_page4。在其初始化過程中建立這5個屬性頁對話框:
    m_page0.Create(IDD_OLE_PROPPAGE_LARGE,GetDlgItem(IDC_TAB1));
            m_page1.Create(IDD_OLE_PROPPAGE_LARGE1,GetDlgItem(IDC_TAB1));
            m_page2.Create(IDD_OLE_PROPPAGE_LARGE2,GetDlgItem(IDC_TAB1));
            m_page3.Create(IDD_OLE_PROPPAGE_LARGE3,GetDlgItem(IDC_TAB1));
            m_page4.Create(IDD_OLE_PROPPAGE_LARGE4,GetDlgItem(IDC_TAB1));
            CRect rs;
            m_tab.GetClientRect(rs);
            rs.top+=20;
            rs.bottom-=3;
            rs.left+=3;
            rs.right-=3;
            m_page0.MoveWindow(rs);
            m_page1.MoveWindow(rs);
            m_page2.MoveWindow(rs);
            m_page3.MoveWindow(rs);
            m_page4.MoveWindow(rs);
            m_page0.ShowWindow(SW_SHOW);
            m_tab.SetCurSel(0);
   然后在選項卡消息TCN_SELCHANGE響應(yīng)函數(shù)中控制它們的顯示:
void CSpyXXDlg::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
            {
            // TODO: Add your control notification handler code here
            int i=m_tab.GetCurSel();
            switch(i)
            {
            case 0:
            m_page0.ShowWindow(SW_SHOW);
            m_page1.ShowWindow(SW_HIDE);
            m_page2.ShowWindow(SW_HIDE);
            m_page3.ShowWindow(SW_HIDE);
            m_page4.ShowWindow(SW_HIDE);
            break;
            case 1:
            m_page0.ShowWindow(SW_HIDE);
            m_page1.ShowWindow(SW_SHOW);
            m_page2.ShowWindow(SW_HIDE);
            m_page3.ShowWindow(SW_HIDE);
            m_page4.ShowWindow(SW_HIDE);
            break;
            case 2:
            ……
            default:
            ;
            }
            *pResult = 0;
            }
  四、常規(guī)標(biāo)簽頁
  常規(guī)標(biāo)簽頁負(fù)責(zé)顯示窗口句柄、窗口類名、標(biāo)題文本、窗口矩形、窗口ID、進程ID和程序路徑??刂破滹@示或改變應(yīng)在CMyPic的WM_LBUTTONUP響應(yīng)函函數(shù)中進行。代碼如下:
((CPage0*)FromHandle(g_hPage0))->m_editHWND.SetWindowText(Display((int)g_hWnd));
            char strClass[200]="\0";
            ::GetClassName(g_hWnd,strClass,200);
            ((CPage0*)FromHandle(g_hPage0))->m_editCLASS.SetWindowText(strClass);
            ((CPage2*)FromHandle(g_hPage2))->SetDlgItemText(IDC_EDITCLASSNAME,strClass);<
            char strTitle[200]="\0";
            ::GetWindowText(g_hWnd,strTitle,200);
            ((CPage0*)FromHandle(g_hPage0))->m_editTITLE.SetWindowText (strTitle);
            long iWNDID=GetWindowLong(g_hWnd,GWL_ID);
            ((CPage0*)FromHandle(g_hPage0))->m_editWNDID.SetWindowText(Display((int)iWNDID));
            unsigned long iPID=0;
            GetWindowThreadProcessId(g_hWnd,&iPID);
            ((CPage0*)FromHandle(g_hPage0))->m_editPID.SetWindowText(Display((int)iPID));
            CString strPath;
            strPath=getProcPath(iPID);
            ((CPage0*)FromHandle(g_hPage0))->m_editPATH.SetWindowText(strPath);
            RECT rc;
            ::GetWindowRect(g_hWnd, &rc); //獲得窗口矩形
            CString strRect;
            strRect.Format("(%d,%d),(%d,%d) %dx%d",rc.left,rc.top,rc.right,rc.bottom,
            rc.right-rc.left,rc.bottom-rc.top);
            ((CPage0*)FromHandle(g_hPage0))->m_editRECT.SetWindowText(strRect);
  其中,getProcPath是獲取進程文件路徑的函數(shù)。獲取進程路徑的方法有兩種。在NT系統(tǒng)中,我們可以用OpenProcess()函數(shù)將進程打開后,再利用EnumProcessModules()函數(shù)枚舉該進程的模塊,最后利用GetModuleFileNameEx()函數(shù)就能取得該進程的路徑;第二種方法是利用ToolHelp API中的相關(guān)函數(shù)。而后者兼容容Windows9x和NT4.0以后系統(tǒng),所以采取此法。它的實現(xiàn)代碼如下:
CString getProcPath(int PID)
            {
            HANDLE hModule;
            MODULEENTRY32* minfo=new MODULEENTRY32;
            minfo->dwSize=sizeof(MODULEENTRY32);
            hModule=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,PID); Module32First(hModule,minfo);
            CString str;
            str.Format("%s",minfo->szExePath);
            CloseHandle(hModule);
            if(minfo) delete minfo;
            return str;
            }
  

  五、樣式標(biāo)簽頁
  樣式標(biāo)簽頁設(shè)計如下圖:

  

  API函數(shù)GetWindowLong可以獲取窗口樣式或擴展樣式的值。然后我們羅列出以WS_開頭的所有窗口樣式與上述樣式值做"位與"操作,如果被包含,則返回其窗口樣式,否則返回0。這樣,就可以得到窗口樣式的列表了。擴展樣式列表與樣式列表類似。相關(guān)代碼如下:

CListBox* pListStyle=(CListBox*)(((CPage1*)FromHandle(g_hPage1))->GetDlgItem(IDC_LIST_STYLE));
            CListBox* pListExStyle=(CListBox*)(((CPage1*)FromHandle(g_hPage1))->GetDlgItem(IDC_LIST_EX_STYLE));
            CEdit* pEditStyle=(CEdit*)(((CPage1*)FromHandle(g_hPage1))->GetDlgItem(IDC_EDIT_STYLE));
            CEdit* pEditExStyle=(CEdit*)(((CPage1*)FromHandle(g_hPage1))->GetDlgItem(IDC_EDIT_EX_STYLE));
            long style = GetWindowLong(g_hWnd, GWL_STYLE);
            long styleEx= GetWindowLong(g_hWnd, GWL_EXSTYLE);
            pEditStyle->SetWindowText(Display((int)style));
            pEditExStyle->SetWindowText(Display((int)styleEx));
            pListStyle->ResetContent(); //清空樣式列表框
            pListExStyle->ResetContent(); //清空擴展樣式列表框
            if (style & WS_BORDER)
            pListStyle->AddString("WS_BORDER");
            if( style & WS_CAPTION)
            pListStyle->AddString("WS_CAPTION");
            if( style & WS_CHILD)
            pListStyle->AddString("WS_CHILD");
            ……
  

  六、類標(biāo)簽頁
  類標(biāo)簽頁的設(shè)計如下圖:

  

  類名在常規(guī)標(biāo)簽頁已獲取。API函數(shù)GetClassLong可以獲取類樣式值。樣式列表的實現(xiàn)與窗口樣式類似,不再贅述。
  

  七、窗口標(biāo)簽頁
  窗口標(biāo)簽頁的設(shè)計如下圖:

  

  在該頁中,主要用到了下面幾個API函數(shù):GetNextWindow、GetWindow和SendMessage。這三個API函數(shù)搭配以不同的參數(shù)值可以實現(xiàn)不同的功能。這里沒有用GetWIndowText函數(shù),是因為它不能取出部分系統(tǒng)窗口和隱藏窗口的標(biāo)題。我們用SendMessage函數(shù)加WM_GETTEXT參數(shù)取代之。代碼如下:

CPage3* pPage3=(CPage3*)FromHandle(g_hPage3);
            HWND tempHandle;
            char tempstr[255]="\0";
            tempHandle = g_hWnd; //本窗口句柄
            pPage3->SetDlgItemText(IDC_MYHWND, Display((int)tempHandle));
            //獲取本窗口標(biāo)題
            ::SendMessage(tempHandle, WM_GETTEXT, 255, (LPARAM)tempstr);
            pPage3->SetDlgItemText(IDC_MYTITLE, tempstr);
            //上一窗口
            tempHandle = ::GetNextWindow(g_hWnd, GW_HWNDPREV);
            pPage3->SetDlgItemText(IDC_PREHWND, Display((int)tempHandle));
            //獲取上一窗口標(biāo)題
            memset(tempstr,0,255);
            ::SendMessage(tempHandle, WM_GETTEXT, 255, (LPARAM)tempstr);
            pPage3->SetDlgItemText(IDC_PRETITLE, tempstr);
            //下一窗口
            tempHandle = ::GetNextWindow(g_hWnd, GW_HWNDNEXT);
            pPage3->SetDlgItemText(IDC_NEXTHWND,Display((int)tempHandle));
            memset(tempstr,0,255); //獲取下一窗口標(biāo)題
            ::SendMessage(tempHandle, WM_GETTEXT, 255, (LPARAM)tempstr);
            pPage3->SetDlgItemText(IDC_NEXTTITLE, tempstr);
            tempHandle = ::GetParent(g_hWnd); //父窗口
            pPage3->SetDlgItemText(IDC_PARENTHWND, Display((int)tempHandle));
            memset(tempstr,0,255);
            ::SendMessage(tempHandle, WM_GETTEXT, 255, (LPARAM)tempstr);
            pPage3->SetDlgItemText(IDC_PARENTTITLE,tempstr);
            //第一子窗口
            tempHandle = ::GetWindow(g_hWnd, GW_CHILD);
            pPage3->SetDlgItemText(IDC_CHILDHWND,Display((int)tempHandle));
            memset(tempstr,-0,255);
            ::SendMessage(tempHandle, WM_GETTEXT, 255, (LPARAM)tempstr);
            pPage3->SetDlgItemText(IDC_CHILDTITLE,tempstr);
            //所有者窗口
            tempHandle = ::GetWindow(g_hWnd, GW_OWNER);
            Page3->SetDlgItemText(IDC_OWNERHWND,Display((int)tempHandle));
            memset(tempstr,0,255);
            ::SendMessage(tempHandle, WM_GETTEXT, 255, (LPARAM)tempstr);
            pPage3->SetDlgItemText(IDC_OWNERTITLE, tempstr);
  

  八、消息標(biāo)簽頁

  消息標(biāo)簽頁的設(shè)計如下圖:

  
該頁中的列表框與樣式列表框不同,它的每個列表項前都有一個復(fù)選框。這要用到類CCheckListBox。這里要再次用到子類化的知識。從本文第一段制作CMyPric過程中,我們體會到了子類化的作用,也感到了它的不便之處。這里,我們采取另外一種方法,借雞生蛋:即用Class Wizard生成相關(guān)代碼,然后再修改它。首先在該屬性頁對話框上畫一個列表控件,打開Class Wizard關(guān)聯(lián)一個CListBox類變量m_listStatus。設(shè)置列表框的Owner Draw屬性為Fixed,并選中其Has Strings選項。如下圖:

      

  然后,在Page4.h中查找到m_listStatus的定義 CListBox m_listStatus并將其改為CCheckListBox m_listStatus。這樣,我們就可以使用CCheckListBox的全部函數(shù)了。
  在對話框初始化過程中添加下列語句以加入各列表項:

CCheckListBox* plistStatus=((CCheckListBox*)FromHandle(g_hPage4)->GetDlgItem(IDC_LISTSTATUS));
            plistStatus->AddString("窗口可見");
            plistStatus->AddString("窗口可用");
            plistStatus->AddString("總在最前");
            plistStatus->AddString("窗口只讀");
            plistStatus->AddString("最大化");
            plistStatus->AddString("最小化");
            plistStatus->AddString("窗口還原");
            plistStatus->AddString("關(guān)閉窗口");
            plistStatus->AddString("激活窗口");
  接下來我們要判斷,當(dāng)窗口/控件被選定后,哪些列表項被勾選。這個判斷過程與樣式列表的實現(xiàn)類似。如第一項"窗口可見",代碼如下:
long style = GetWindowLong(g_hWnd, GWL_STYLE);
            if( style & WS_VISIBLE )
            {
            pListStatus->SetCheck(0,1);
            }
  其余各項詳見源代碼。 這個列表框的作用不僅僅是顯示窗口的狀態(tài),還要在發(fā)生勾選改動時即時改變窗口狀態(tài)或激發(fā)其行為。勾選狀態(tài)改變的消息是LBN_SELCHANGE。另外,為了不使一個勾選的改變就引起所有列表項都激發(fā)一遍,我們采用switch結(jié)構(gòu),以使哪個列表項被選中就激發(fā)哪個列表項。代碼如下:
void CPage4::OnSelchangeListstatus()
            {
            // TODO: Add your control notification handler code here
            int n=m_listStatus.GetCurSel();
            switch(n)
            {
            case 0:
            if(m_listStatus.GetCheck(0)== 1 )
            ::ShowWindow(g_hWnd, SW_SHOW);
            else
            ::ShowWindow(g_hWnd, SW_HIDE);
            break;
            case 1:
            if(m_listStatus.GetCheck(1) == 1)
            ::EnableWindow(g_hWnd, TRUE);
            else
            ::EnableWindow(g_hWnd,FALSE);
            break;
            case 2:
            if(m_listStatus.GetCheck(2) == 1)
            ::SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
            else
            ::SetWindowPos(g_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
            break;
            case 3:
            if(m_listStatus.GetCheck(3) == 1)
            ::SendMessage(g_hWnd, EM_SETREADONLY, TRUE, 0);
            else
            ::SendMessage(g_hWnd, EM_SETREADONLY, FALSE, 0);
            break;
            case 4:
            if(m_listStatus.GetCheck(4) ==1)
            {
            ::ShowWindow(g_hWnd, SW_MAXIMIZE);
            m_listStatus.SetCheck(5,0);
            }
            else
            ::ShowWindow (g_hWnd, SW_RESTORE);
            break;
            case 5:
            if (m_listStatus.GetCheck(5) == 1)
            {
            ::ShowWindow(g_hWnd, SW_MINIMIZE);
            m_listStatus.SetCheck(4,0);
            }
            else
            ::ShowWindow(g_hWnd, SW_RESTORE);
            break;
            case 6:
            if(m_listStatus.GetCheck(6) ==1)
            {
            ::ShowWindow (g_hWnd, SW_RESTORE);
            m_listStatus.SetCheck(6,0);
            m_listStatus.SetCheck(5,0);
            m_listStatus.SetCheck(4,0);
            }
            break;
            case 7:
            if(m_listStatus.GetCheck(7) ==1)
            {
            ::SendMessage (g_hWnd, WM_CLOSE, 0, 0);
            m_listStatus.SetCheck(7,0);
            }
            break;
            case 8:
            if(m_listStatus.GetCheck(8) ==1)
            {
            ::BringWindowToTop(g_hWnd);
            m_listStatus.SetCheck(8,0);
            }
            break;
            default:
            ;
            }
            }
  Spy++打造完畢?;仡櫰溥^程,難點不多,細(xì)細(xì)碎碎問題不少。也難免啊,不僅要形似,咱還要神似。文中一定還有很多地方不夠周全,希望同行朋友們不吝賜教。代碼在Window XP + VC6.0中調(diào)試通過。Spy++源碼同時放在這里。歡迎訪問我的個人主頁(阿珊境界)http://www.,歡迎加入我們的VC討論群713035。

 

 


(#)

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多