日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

VC++开发股票软件

發(fā)布時(shí)間:2023/12/20 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VC++开发股票软件 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

VC炒股軟件開(kāi)發(fā)

文檔說(shuō)明:

此文檔適合VC++的初學(xué)者,高手也可參考(希望能提出寶貴意見(jiàn))。

開(kāi)發(fā)前準(zhǔn)備:

這是一個(gè)根據(jù)股票信息的數(shù)據(jù)繪的幾個(gè)制界面,數(shù)據(jù)來(lái)源通信達(dá)軟件的數(shù)據(jù)文件,通常在安裝了通信達(dá)以后并下載數(shù)據(jù)到本地以后就有了。

1.數(shù)據(jù)文件的準(zhǔn)備:

假如你安裝通信達(dá)的目錄是:D:\jcb_gx。那么對(duì)應(yīng)的數(shù)據(jù)文件就在D:\jcb_gx\vipdoc\目錄下,里面每一個(gè)目錄下就是一類(lèi)股票的數(shù)據(jù),我們開(kāi)發(fā)這個(gè)界面需要用到的是每個(gè)目錄下的lday目錄下的.lday后綴名的文件。每一個(gè)文件里面存放的是一支滾票的數(shù)據(jù)信息。我當(dāng)時(shí)開(kāi)發(fā)用到了兩類(lèi)股票的信息,分別對(duì)應(yīng)的目錄是:D:\jcb_gx\vipdoc\sh\lday和D:\jcb_gx\vipdoc\sz\lday。其實(shí)每類(lèi)開(kāi)發(fā)的方法完全一樣,唯一不同就是讀取不同的目錄而已。

2.文件數(shù)據(jù)結(jié)構(gòu):

準(zhǔn)備好數(shù)據(jù)以后,還有一點(diǎn)是必須知道的,不然也沒(méi)有辦法進(jìn)行下去,就是文件里面的數(shù)據(jù)格式是怎樣的。因?yàn)槲矣玫氖峭ㄐ胚_(dá)的數(shù)據(jù)文件,所以只需要在www.g.cn查詢(xún)通信達(dá)的數(shù)據(jù)格式就可以了,如下:

typedef struct { //共32字節(jié)int date; //4字節(jié) 如20091229int open; //開(kāi)盤(pán)價(jià)int high; //最高價(jià)int low; //最低價(jià)int close; //收盤(pán)價(jià)float amount; //成交額int vol; //成交量int reservation; //保留值 } StockData;

詳細(xì)開(kāi)發(fā)過(guò)程(包括我的思路和具體實(shí)現(xiàn)):

1.實(shí)現(xiàn)如上圖的界面,需要做如下事情

(1)讀一個(gè)目錄下的所有文件,并從文件名中提取出相應(yīng)股票的代碼

可行性分析:

首先我們打開(kāi)的是一個(gè)目錄,然后從這個(gè)目錄中讀出里面所有的文件名,目錄存放的內(nèi)容其實(shí)就是此目錄下的文件名或目錄名。用到兩個(gè)函數(shù),一個(gè)FindFirstFile查找到一個(gè)目錄下的第一個(gè)文件名,另一個(gè)FindNextFile查找下一個(gè)文件名。這樣就可以遍歷一個(gè)目錄下的所有文件名了。

具體實(shí)現(xiàn):

BOOLCTongXinDaView::ReadFileData(LPCSTR path) {//path是這種形式的參數(shù):D:\\jcb_gx\\vipdoc\\sh\\lday\\*m_iCount = 0;WIN32_FIND_DATA tFind = {0};int i = 0;CString strTemp;HANDLE hSearch = ::FindFirstFile(path, &tFind); if (hSearch == INVALID_HANDLE_VALUE) { return FALSE; } //過(guò)濾掉.和..文件::FindNextFile(hSearch, &tFind);while (::FindNextFile(hSearch, &tFind)){strTemp.Format("%s",tFind.cFileName);m_File[i].Format("%s",path);//去掉查詢(xún)用到的*通配符m_File[i] =m_File[i].Left(m_File[i].GetLength()-1);m_File[i] +=strTemp;//從文件名中提取股票代碼m_FileName[i] =strTemp.Mid(2, 6);i++;}m_iPageCount = i / 31 + 1; //求出需要顯示的總頁(yè)面數(shù)m_iLeave = i % 31; //最后一頁(yè)顯示的數(shù)據(jù)m_CurrFile = m_File[m_iCount]; //保存選中的文件名::FindClose(hSearch); return TRUE; }

注意事項(xiàng):每一個(gè)目錄下都有這兩個(gè)目錄文件:“.”和“..”。它們分別代表本目錄和父目錄(就是上層目錄),必須過(guò)濾掉這兩個(gè)目錄文件。還好每次這兩個(gè)目錄文件總是最先被讀出,所以前兩次讀出來(lái)的信息直接不管就可以了。

上面的函數(shù)被相應(yīng)的每一個(gè)菜單項(xiàng)事件調(diào)用,就是針對(duì)不同的股票用一個(gè)菜單項(xiàng)打開(kāi)。

(2)頁(yè)面的顯示:

可行性分析:

先說(shuō)說(shuō)我當(dāng)時(shí)需要完成的現(xiàn)實(shí)任務(wù),每頁(yè)顯示31行(具體可以變動(dòng),但是31 行效果比較好),顯示3列,第一列索引號(hào),也就是起個(gè)計(jì)數(shù)的作用,第二列就是剛才我們提取到的股票代碼號(hào),第三列隨便填充4個(gè)漢字。還要求畫(huà)一條線(xiàn)表示當(dāng)前選中的股票,鼠標(biāo)上下滾動(dòng)和PageDown,PageUp按鍵實(shí)現(xiàn)上下翻頁(yè)功能,鼠標(biāo)點(diǎn)擊選中點(diǎn)擊最近的一支股票,按鍵上下鍵也可以移動(dòng)股票選擇。明白了需要實(shí)現(xiàn)的功能,我現(xiàn)在就一步一步來(lái)完成。這里需要用到文字輸出函數(shù)DrawText。

具體實(shí)現(xiàn):

void CTongXinDaView::DrawText(CDC *pDC, int page) {CRect rt;GetClientRect(&rt);int high = rt.Width() / 55;int y = high;//控制每一行顯示數(shù)據(jù)的增量CString strLine;int number = 1;pDC->SetBkMode(TRANSPARENT);pDC->SetTextColor(RGB(200, 200, 200));strLine.Format(" 代碼 名稱(chēng) 日期 開(kāi)牌價(jià) 最高價(jià) 最低價(jià) 收盤(pán)價(jià) 多多 成交量 ");pDC->TextOut(0, 0, strLine);//控制最后一頁(yè)只顯示剩余的 if (page == m_iPageCount-1){for (int i=page * SCREENHEIGHT; i<(page*SCREENHEIGHT + m_iLeave); i++){if (i == m_iCount){CPen pen(PS_SOLID, 1, RGB(255, 255, 0));CPen *pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(50, y+high-5);pDC->LineTo(rt.right, y+high-5);pDC->SelectObject(pOldPen);}strLine.Format("%d", i+1);pDC->DrawText(strLine, CRect(0, y, 40, y+high), DT_RIGHT);pDC->DrawText(m_FileName[i], CRect(50, y, 100, y+high), DT_LEFT);pDC->DrawText("長(zhǎng)城開(kāi)發(fā)", CRect(110, y, 180, y+high), DT_LEFT);y = y + high;}} else{for (int i=page * SCREENHEIGHT; i<(page+1)*SCREENHEIGHT; i++){if (i == m_iCount){CPen pen(PS_SOLID, 1, RGB(255, 255, 0));CPen *pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(50, y+high-7);pDC->LineTo(rt.right, y+high-7);pDC->SelectObject(pOldPen);}strLine.Format("%d", i+1);pDC->DrawText(strLine, CRect(0, y, 40, y+high), DT_RIGHT);pDC->DrawText(m_FileName[i], CRect(50, y, 100, y+high), DT_LEFT);pDC->DrawText("長(zhǎng)城開(kāi)發(fā)", CRect(110, y, 180, y+high), DT_LEFT);y = y + high;}} }

注意事項(xiàng):

1.最后一頁(yè)數(shù)據(jù)條目不夠,需要特殊處理。

2.輸出函數(shù)用的是DawText而不是TextOut,是為了使輸出對(duì)齊。

3.鼠標(biāo)和按鍵的響應(yīng)只是簡(jiǎn)單邏輯處理和顯示不同的數(shù)據(jù)。

(3)分頁(yè)顯示和選取當(dāng)前一支股票的實(shí)現(xiàn)思想說(shuō)明:

可行性分析:

上面已經(jīng)實(shí)現(xiàn)了頁(yè)面的顯示,現(xiàn)在說(shuō)說(shuō)怎樣控制上下翻頁(yè)和鼠標(biāo)鍵盤(pán)實(shí)現(xiàn)選中一支股票(我是用一條黃色的線(xiàn)標(biāo)示)。上下翻頁(yè)時(shí)通過(guò)鍵盤(pán)上的PageDown和PageUp,還有鼠標(biāo)滾輪控制的。其實(shí)原理很簡(jiǎn)單,只需要我們?cè)谧x目錄下每個(gè)股票文件時(shí)記錄一下這個(gè)目錄下的股票數(shù)量,也就是我們需要顯示的所有行數(shù)。我們一個(gè)常量記錄每一頁(yè)顯示的數(shù)目,用總數(shù)除以這個(gè)數(shù)就是總共需要的頁(yè)數(shù)。然后用一個(gè)變量記錄當(dāng)前顯示的是第幾頁(yè),上下翻頁(yè)就是對(duì)這個(gè)變量的加減操作了。選中一支股票則是根據(jù)我們點(diǎn)擊的鼠標(biāo)的位置來(lái)決定,因?yàn)槊恳恍兴嫉捻?yè)面寬度是一樣的,只需要判斷點(diǎn)擊在哪一行所處的位置就可以了。當(dāng)然也需要用變量記錄選中的是那一只股票,總數(shù)剛才我們也記錄了,所以很容易記錄當(dāng)前的哪一只股票,只是需要注意翻頁(yè)后選擇的股票相應(yīng)的加減一頁(yè)的顯示的股票數(shù)。最后一點(diǎn)就是注意一些邊界條件的處理。

2.實(shí)現(xiàn)如下圖的界面:

(1)讀取選中的股票文件,并保存以為繪圖使用這些數(shù)據(jù)

可行性分析:

按照固定的數(shù)據(jù)格式把文件中的數(shù)據(jù)讀入到一個(gè)結(jié)構(gòu)體中保存,用fread每次讀入固定長(zhǎng)度的數(shù)據(jù)格式接可以了。

具體實(shí)現(xiàn):

/* * 函數(shù)名稱(chēng): ReadData * 輸 入: * 輸 出: * 功能描述: 從當(dāng)前文件中讀取數(shù)據(jù) * 全局變量: * 作 者: 吳友強(qiáng) * 日 期: 2009年11月29日 * 修 改: * 日 期: */ void CTongXinDaView::ReadData() {FILE *fp;m_iDataItemCount = -1;//打開(kāi)當(dāng)前文件if ((fp = fopen(m_CurrFile, "rb")) == NULL){return ;}while (!feof(fp)){m_iDataItemCount++;fread(&m_StockData[m_iDataItemCount],sizeof(StockData),1,fp);//求最大的日期if (m_StockData[m_iDataItemCount].date > m_iMaxDate){m_iMaxDate = m_StockData[m_iDataItemCount].date;}//求最小的日期if (m_iDataItemCount == 0){m_iMinDate = m_StockData[m_iDataItemCount].date;}else if (m_StockData[m_iDataItemCount].date > 0 && m_StockData[m_iDataItemCount].date < m_iMinDate){m_iMinDate = m_StockData[m_iDataItemCount].date;}}m_iDataItemCount--;//去掉最后一條無(wú)用的記錄m_iStartDay = m_iDataItemCount;if (m_iDays > m_iDataItemCount){m_iDays = m_iDataItemCount+1;} //以前在這里沒(méi)有關(guān)閉文件,所以當(dāng)打開(kāi)一定數(shù)量的時(shí)候(windows限制的)在打開(kāi)文件就會(huì)失敗fclose(fp); }

(2)提取當(dāng)前需要顯示的數(shù)據(jù):

可行性分析:

根據(jù)當(dāng)前需要顯示多少天的數(shù)據(jù)來(lái)提取,從上面我們從文件里面讀取的數(shù)據(jù)中提取,以后的所謂放大縮小,左右移動(dòng)就是提取不同天的數(shù)據(jù)就是了。

具體實(shí)現(xiàn):

/* * 函數(shù)名稱(chēng): GetStockData * 輸 入: days * days: 屏幕需要顯示的天數(shù) * 輸 出: * 功能描述: 得到顯示的數(shù)據(jù)和求取各個(gè)最值 * 全局變量: * 作 者: 吳友強(qiáng) * 日 期: 2009年11月30日 * 修 改: * 日 期: */ void CTongXinDaView::GetStockData(int days) {m_iLowMax = 0;m_iHighMax = 0;m_iVolMax = 0;if (m_sdCurrData != NULL){delete m_sdCurrData;}m_sdCurrData = new StockData[days];for (int i=0; i<days; i++){m_sdCurrData[days-i-1] = m_StockData[m_iStartDay-i-1];//求本次顯示成交量的最大值if (m_sdCurrData[days-i-1].vol > m_iVolMax){m_iVolMax = m_sdCurrData[days-i-1].vol;}//求本次顯示最高值的最大值if (m_sdCurrData[days-i-1].high > m_iHighMax){m_iHighMax = m_sdCurrData[days-i-1].high;} //求本次顯示最低值的最小值if (i == 0){m_iLowMax = m_sdCurrData[days-i-1].low;}else if (m_sdCurrData[days-i-1].low < m_iLowMax){m_iLowMax = m_sdCurrData[days-i-1].low;}} }

(3)得到需要顯示的數(shù)據(jù)以后,我們就可以開(kāi)始繪圖了

可行性分析:

我們得到需要顯示的數(shù)據(jù)以后,就需要根據(jù)當(dāng)前顯示的寬度和高度來(lái)劃分屏幕了,根據(jù)客戶(hù)的需求大致需要把屏幕分為上中下三部分,第一部分畫(huà)成交量的平均值線(xiàn)和一天中的最高值到最低值的一條豎線(xiàn),還有開(kāi)盤(pán)價(jià)和收盤(pán)價(jià)的矩形圖;第二部分成交總量;第三部分成交價(jià)格除以2,3,4,5刻度控制在-4到4資料的線(xiàn)形圖。首先我們必須確定三部分的高度,然后把3個(gè)坐標(biāo)固定下來(lái)并繪畫(huà)出來(lái),至于坐標(biāo)的刻度我們可以動(dòng)態(tài)的根據(jù)每次需要顯示的數(shù)據(jù)的最大值和最小值來(lái)計(jì)算確定,然后根據(jù)刻度的比例來(lái)畫(huà)所有的圖形。其中很多需要計(jì)算,具體的情看代碼。下面是整個(gè)系統(tǒng)的黑心部分,具體請(qǐng)看代碼注釋。

具體實(shí)現(xiàn):

/* * 函數(shù)名稱(chēng): DrawGraphic * 輸 入: pDC, days * pDC: 畫(huà)圖的CDC指針 * days: 顯示數(shù)據(jù)的天數(shù) * 輸 出: * 功能描述: 畫(huà)各種坐標(biāo)以及圖形 * 全局變量: * 作 者: 吳友強(qiáng) * 日 期: 2009年11月29日 * 修 改: 吳友強(qiáng) * 日 期: 2009年12月4日 */ void CTongXinDaView::DrawGraphic(CDC *pDC, int days) { //設(shè)置透明繪圖模式pDC->SetBkMode(TRANSPARENT);pDC->SetTextColor(RGB(200, 0 ,0));CRect rt;GetClientRect(&rt);float average;float averPri;float ftemp, ftext;CString str;int i = 0;float xAver;pDC->DrawText("當(dāng)前代碼: " + m_FileName[m_iCount], CRect(0, 0, 200, 20), DT_LEFT);//初始化各個(gè)坐標(biāo)原點(diǎn)m_ptOrigin[0].x = rt.Width()-100;m_ptOrigin[0].y = rt.Height()/8 * 3;m_ptOrigin[1].x = rt.Width()-100;m_ptOrigin[1].y = rt.Height()/4 * 2;m_ptOrigin[2].x = rt.Width()-100;m_ptOrigin[2].y = rt.Height()/4 * 3;//劃分屏幕為三部分CPen penRedSolid(PS_SOLID, 1, RGB(200, 0, 0));CPen *pOldPen = pDC->SelectObject(&penRedSolid);pDC->MoveTo(0, m_ptOrigin[0].y);pDC->LineTo(rt.Width(), m_ptOrigin[0].y);pDC->MoveTo(0, m_ptOrigin[1].y);pDC->LineTo(rt.Width(), m_ptOrigin[1].y);pDC->MoveTo(0, m_ptOrigin[2].y);pDC->LineTo(rt.Width()-100, m_ptOrigin[2].y);pDC->MoveTo(rt.Width()-100, 0);pDC->LineTo(rt.Width()-100, rt.Height());//每一天顯示的寬度xAverxAver = (rt.Width()-100) / (float)days;//平均刻度代表的價(jià)格averPri = (m_iHighMax-m_iLowMax) / 5.0 / 100;//第一條價(jià)格起始線(xiàn)ftemp = m_iLowMax/ 100.0;//刻度線(xiàn)的距離average = m_ptOrigin[0].y / 6.0;CPen penRedDot(PS_DOT, 1, RGB(200, 0, 0));//畫(huà)K線(xiàn)坐標(biāo)for (i=0; i<5; i++){pDC->SelectObject(&penRedDot);pDC->MoveTo(0, average*(i+1));pDC->LineTo(rt.Width()-100, average*(i+1));pDC->SelectObject(&penRedSolid);pDC->LineTo(rt.Width()-100+10, average*(i+1));pDC->MoveTo(rt.Width()-100, average*(i+1) + average/2);pDC->LineTo(rt.Width()-100+5, average*(i+1) + average/2);pDC->MoveTo(rt.Width()-100, average*(i+1) + average/4);pDC->LineTo(rt.Width()-100+3, average*(i+1) + average/4);pDC->MoveTo(rt.Width()-100, average*(i+1) + average/4*3);pDC->LineTo(rt.Width()-100+3, average*(i+1) + average/4*3);str.Format("%10.2f", ftemp + averPri * (5-i));pDC->DrawText(str, CRect(rt.Width()-100, average*(i+1)-7, rt.Width(), average*(i+1)+10), DT_LEFT);}CPen penGreen(PS_SOLID, 1, RGB(0, 200, 0));CBrush brush(NULL_BRUSH);CBrush brushGreen(RGB(0, 200, 0));CBrush *pOldBrush = pDC->SelectObject(&brush);//畫(huà)每天最低到最高的線(xiàn),開(kāi)盤(pán)和收盤(pán)的矩形for (i=0; i<days; i++){if (m_sdCurrData[i].open <= m_sdCurrData[i].close){pDC->SelectObject(&penRedSolid);pDC->SelectObject(&brush);pDC->MoveTo(xAver * i+xAver/3, average*5- average/averPri*(m_sdCurrData[i].high/100.0-ftemp));pDC->LineTo(xAver * i+xAver/3, average*5- average/averPri*(m_sdCurrData[i].low/100.0-ftemp));pDC->Rectangle(xAver*i, average*5-average/averPri*(m_sdCurrData[i].open/100.0- ftemp),xAver*i+xAver/3*2, average*5-average/averPri*(m_sdCurrData[i].close/100.0- ftemp));}else{pDC->SelectObject(&penGreen);pDC->SelectObject(&brushGreen);pDC->MoveTo(xAver * i+xAver/3, average*5- average/averPri*(m_sdCurrData[i].high/100.0-ftemp));pDC->LineTo(xAver * i+xAver/3, average*5- average/averPri*(m_sdCurrData[i].low/100.0-ftemp));pDC->Rectangle(xAver*i, average*5-average/averPri*(m_sdCurrData[i].close/100.0- ftemp),xAver*i+xAver/3*2, average*5-average/averPri*(m_sdCurrData[i].open/100.0- ftemp));}if (!m_bMouseMove){if (m_iDrawCount == i){m_ptSavePoint.x = xAver * i+xAver/3;m_ptSavePoint.y = average*5-average/averPri*(m_sdCurrData[i].open/100.0-ftemp);}}}//計(jì)算5日平均值和10日平均值int *fiveAverData = new int[days];int *tenAverData = new int[days];for (i=0; i<days; i++){if (i >= 4){fiveAverData[i] = (m_sdCurrData[i].close + m_sdCurrData[i-1].close +m_sdCurrData[i-2].close + m_sdCurrData[i-3].close + m_sdCurrData[i-4].close) / 5;}else{fiveAverData[i] = m_sdCurrData[i].close * 5 / 5;}if (i >= 9){tenAverData[i] = (m_sdCurrData[i].close + m_sdCurrData[i-1].close +m_sdCurrData[i-2].close + m_sdCurrData[i-3].close + m_sdCurrData[i-4].close + m_sdCurrData[i-5].close +m_sdCurrData[i-6].close +m_sdCurrData[i-7].close + m_sdCurrData[i-8].close +m_sdCurrData[i-9].close) / 10;}else{tenAverData[i] = m_sdCurrData[i].close * 10 / 10;} }//畫(huà)5日均線(xiàn)和10日均線(xiàn)CPen penWhite(PS_SOLID, 1, RGB(200, 200, 200));CPen penYellow(PS_SOLID, 1, RGB(200, 200, 0));for (i=1; i<days; i++){ pDC->SelectObject(&penWhite);pDC->MoveTo(xAver * (i-1)+xAver/3, average*5-average/averPri*(fiveAverData[i-1]/100.0-ftemp));pDC->LineTo(xAver * i+xAver/3, average*5-average/averPri*(fiveAverData[i]/100.0-ftemp));pDC->SelectObject(&penYellow);pDC->MoveTo(xAver * (i -1)+xAver/3, average*5-average/averPri*(tenAverData[i-1]/100.0-ftemp));pDC->LineTo(xAver * i+xAver/3, average*5-average/averPri*(tenAverData[i]/100.0-ftemp));}//畫(huà)柱狀成交量的坐標(biāo)和柱狀圖average = (m_ptOrigin[1].y - m_ptOrigin[0].y) / 5;float averVol = m_iVolMax / 4.0;int temp = m_iVolMax / 4 / 100000 * 1000;//顯示刻度用的臨時(shí)變量pDC->SelectObject(&penRedSolid);pDC->SelectObject(&brush);str.Format("%s", " X100");pDC->Rectangle(rt.Width()-100, m_ptOrigin[1].y-10, rt.Width()-50, m_ptOrigin[1].y+5);pDC->DrawText(str, CRect(rt.Width()-100, m_ptOrigin[1].y-10, rt.Width(), m_ptOrigin[1].y+5), DT_LEFT);for (i=0; i<4; i++){pDC->SelectObject(&penRedDot);pDC->MoveTo(0, m_ptOrigin[0].y + average*(i+1));pDC->LineTo(rt.Width()-100, m_ptOrigin[0].y + average*(i+1));pDC->SelectObject(&penRedSolid);pDC->LineTo(rt.Width()-100+10, m_ptOrigin[0].y + average*(i+1));pDC->MoveTo(rt.Width()-100, m_ptOrigin[0].y + average*(i+1) + average / 2);pDC->LineTo(rt.Width()-100+5, m_ptOrigin[0].y + average*(i+1) + average / 2);str.Format("%10d", temp * (4-i));pDC->DrawText(str, CRect(rt.Width()-100, m_ptOrigin[0].y + average*(i+1)-7, rt.Width(), m_ptOrigin[0].y + average*(i+1)+10), DT_LEFT);}for (i=0; i<days; i++){if (m_sdCurrData[i].open <= m_sdCurrData[i].close){pDC->SelectObject(&penRedSolid);pDC->SelectObject(&brush);}else{pDC->SelectObject(&penGreen);pDC->SelectObject(&brushGreen);}pDC->Rectangle(xAver*i, m_ptOrigin[1].y - m_sdCurrData[i].vol / averVol * average,xAver*i+xAver/3*2, m_ptOrigin[1].y);}//1.畫(huà)收盤(pán)價(jià)四色線(xiàn)的刻度值average = (m_ptOrigin[2].y - m_ptOrigin[1].y) / 5;str.Format("%8d", 0);pDC->DrawText(str, CRect(rt.Width()-100, m_ptOrigin[2].y-7, rt.Width(), m_ptOrigin[2].y+10), DT_LEFT);for (i=0; i<4; i++){pDC->SelectObject(&penRedDot);pDC->MoveTo(0, m_ptOrigin[1].y + average*(i+1));pDC->LineTo(rt.Width()-100, m_ptOrigin[1].y + average*(i+1));pDC->SelectObject(&penRedSolid);pDC->LineTo(rt.Width()-100+10, m_ptOrigin[1].y + average*(i+1));for (int j=0; j<10; j++){pDC->MoveTo(rt.Width()-100, m_ptOrigin[1].y + average*(i+1) + average / 10 *(j+1));pDC->LineTo(rt.Width()-100+5, m_ptOrigin[1].y + average*(i+1) + average / 10*(j+1));}pDC->SelectObject(&penRedDot);pDC->MoveTo(0, m_ptOrigin[2].y + average*(i+1));pDC->LineTo(rt.Width()-100, m_ptOrigin[2].y + average*(i+1));pDC->SelectObject(&penRedSolid);pDC->LineTo(rt.Width()-100+10, m_ptOrigin[2].y + average*(i+1));for (j=0; j<10; j++){pDC->MoveTo(rt.Width()-100, m_ptOrigin[2].y + average*i + average / 10 *(j+1));pDC->LineTo(rt.Width()-100+5, m_ptOrigin[2].y + average*i + average / 10*(j+1));}str.Format("%8d", 4-i);pDC->DrawText(str, CRect(rt.Width()-100, m_ptOrigin[1].y + average*(i+1)-7, rt.Width(), m_ptOrigin[1].y + average*(i+1)+10), DT_LEFT);str.Format("%8d", -(i+1));pDC->DrawText(str, CRect(rt.Width()-100, m_ptOrigin[2].y + average*(i+1)-7, rt.Width(), m_ptOrigin[2].y + average*(i+1)+10), DT_LEFT);}//2.計(jì)算四線(xiàn)的點(diǎn)值float *fPrice1 = new float[days];float *fPrice2 = new float[days];float *fPrice3 = new float[days];float *fPrice4 = new float[days];for (i=0; i<days; i++){fPrice1[i] = m_sdCurrData[i].close / 100.0 / 2 - m_sdCurrData[i].close / 100 / 2 + m_sdCurrData[i].close / 100 / 2 % 4;fPrice2[i] = m_sdCurrData[i].close / 100.0 / 3 - m_sdCurrData[i].close / 100 / 3 + m_sdCurrData[i].close / 100 / 3 % 4;fPrice3[i] = m_sdCurrData[i].close / 100.0 / 4 - m_sdCurrData[i].close / 100 / 4 + m_sdCurrData[i].close / 100 / 4 % 4;fPrice4[i] = m_sdCurrData[i].close / 100.0 / 5 - m_sdCurrData[i].close / 100 / 5 + m_sdCurrData[i].close / 100 / 5 % 4;}for (i=0; i<days-1; i++){pDC->SelectObject(&penWhite);pDC->MoveTo(xAver*i, m_ptOrigin[2].y-average * fPrice1[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y-average *fPrice1[i+1]);pDC->MoveTo(xAver*i, m_ptOrigin[2].y+average * fPrice1[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y+average *fPrice1[i+1]);pDC->SelectObject(&penYellow);pDC->MoveTo(xAver*i, m_ptOrigin[2].y-average * fPrice2[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y-average *fPrice2[i+1]);pDC->MoveTo(xAver*i, m_ptOrigin[2].y+average * fPrice2[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y+average *fPrice2[i+1]);pDC->SelectObject(&penRedSolid);pDC->MoveTo(xAver*i, m_ptOrigin[2].y-average * fPrice3[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y-average *fPrice3[i+1]);pDC->MoveTo(xAver*i, m_ptOrigin[2].y+average * fPrice3[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y+average *fPrice3[i+1]);pDC->SelectObject(&penGreen);pDC->MoveTo(xAver*i, m_ptOrigin[2].y-average * fPrice4[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y-average *fPrice4[i+1]);pDC->MoveTo(xAver*i, m_ptOrigin[2].y+average * fPrice4[i]);pDC->LineTo(xAver*(i+1), m_ptOrigin[2].y+average *fPrice4[i+1]);}DrawDateText(pDC);//釋放動(dòng)態(tài)分配的內(nèi)存delete fiveAverData;delete tenAverData;delete fPrice1;delete fPrice2;delete fPrice3;delete fPrice4;//還原繪畫(huà)環(huán)境pDC->SelectObject(pOldPen);pDC->SelectObject(pOldBrush); }

說(shuō)明:上面最麻煩的是數(shù)據(jù)的處理,如果處理不好就不能把圖畫(huà)到合適的位置,所以計(jì)算的時(shí)候一定要用float,不然就算是很小的數(shù)據(jù)差別都會(huì)造成繪圖不到指定的位置。還有這個(gè)函數(shù)代碼量比較多,是因?yàn)槔L圖都需要用到平均每天的寬度和一些公用的參數(shù),所以就在一個(gè)函數(shù)里完成了。其實(shí)可以寫(xiě)成很多個(gè)函數(shù)模塊,比如每一個(gè)部分可以寫(xiě)成一個(gè)函數(shù),然后數(shù)據(jù)計(jì)算可以用專(zhuān)門(mén)的函數(shù)封裝。

(3)補(bǔ)充功能,在最下面顯示當(dāng)前鼠標(biāo)對(duì)應(yīng)的日期

/* * 函數(shù)名稱(chēng): DrawDateText * 輸 入: pDC * pDC: 繪畫(huà)用的CDC指針 * 輸 出: * 功能描述: 顯示日期 * 全局變量: * 作 者: 吳友強(qiáng) * 日 期: 2009年12月02日 * 修 改: * 日 期: */ void CTongXinDaView::DrawDateText(CDC *pDC) {CRect rt;GetClientRect(&rt);float xAver;CString strDate;xAver = (rt.Width()-100) / (float)m_iDays;for (int i=0; i<m_iDays; i++){if ((m_ptDatePoint.x > xAver * i) && (m_ptDatePoint.x < (xAver * i+xAver / 3 *2))){m_iDateCount = i;}}CPen pen(PS_SOLID, 1, RGB(200, 0, 0));CPen *pOldPen = pDC->SelectObject(&pen);CBrush brushBlue(RGB(0, 0, 150));CBrush *pOldBrush = pDC->SelectObject(&brushBlue);pDC->SetTextColor(RGB(200, 200, 200));pDC->MoveTo(0, rt.Height()-15);pDC->LineTo(rt.Width()-100, rt.Height()-15);strDate.Format("%d", m_sdCurrData[m_iDateCount]);strDate.Insert(4, '/');strDate.Insert(7, '/');pDC->Rectangle(m_ptDatePoint.x, rt.Height()-15, m_ptDatePoint.x+75, rt.Height());pDC->DrawText(strDate, CRect(m_ptDatePoint.x, rt.Height()-15, m_ptDatePoint.x+75, rt.Height()), DT_LEFT);pDC->SelectObject(&pOldPen);pDC->SelectObject(&pOldBrush); }

說(shuō)明:為了顯示出這個(gè)日期,需要記錄當(dāng)前屏幕繪畫(huà)了哪些天的圖,然后根據(jù)鼠標(biāo)的坐標(biāo)位置判斷處于哪一天并顯示出來(lái)。

(4)圖形放大縮小以及左右平移的實(shí)現(xiàn)思路:

其實(shí)原理都是一樣的,就是根據(jù)需要的天數(shù)顯示,放大就是顯示的天數(shù)比較少,縮小就是多顯示一些天數(shù),左右移動(dòng)就是重新提取一些數(shù)據(jù)。顯示的天數(shù)可以根據(jù)需要按照固定需要按固定的比例放大和縮小。然后就是通過(guò)一些按鍵來(lái)控制或是鼠標(biāo)控制,其中還有一個(gè)輔助線(xiàn)的設(shè)置比較靠邏輯,需要細(xì)心才能弄好。具體的請(qǐng)參看代碼,有注釋。

3.心得體會(huì):

剛開(kāi)始的時(shí)候感覺(jué)什么都不會(huì),但是我還是勇敢地邁出了自己的第一步,因?yàn)樵谶@幾年的學(xué)習(xí)過(guò)程中我發(fā)現(xiàn)自己解決問(wèn)題的能力提升了很多,所以相信自己能夠完成。然后自己就靜下心來(lái)一行一行代碼的寫(xiě),經(jīng)過(guò)幾天努力,完成了大部分功能,自己的信心也是越來(lái)越強(qiáng)。現(xiàn)在這個(gè)程度還算過(guò)的去了吧。

4.存在的不足:

由于對(duì)于股票行業(yè)術(shù)語(yǔ)不是很了解,很多變量的命名不是很合理和規(guī)范,代碼的組織也不是很好。

5.得到的幫助與指導(dǎo):

感謝老師提供的思路,特別是對(duì)于所謂的圖形放大和縮小,左右移動(dòng),老師的提醒使我恍然大悟,以后基本上沒(méi)有什么太大的困難。就是數(shù)據(jù)的提取問(wèn)題。

總結(jié)

以上是生活随笔為你收集整理的VC++开发股票软件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。