您的位置:首页 > 产品设计 > UI/UE

编辑框自动滚屏到最后

2016-05-26 17:47 330 查看
描述一个编辑框自动滚屏的例子,同时利用worker线程+定时器=UI线程的方式刷新UI。

要点

定时器

worker线程+定时器=UI线程

示例UI



示例功能

Start之后,编辑框中显示Line 1, Line 2, Line 3,。。。Stop之后,停止增加Line n字符串。

在代码实现中,Start之后启动一个线程,每隔一秒新增一个Line n字符串,更新到对话框的m_sMsg字符串变量中。另外,对话框在Start之后启动一个1s定时器,周期性刷新UI。

Stop之后,停止线程,杀掉定时器。

示例代码

rc

重点关注CEdit控件的属性。

IDD_CEDITEXAMPLE_DIALOG DIALOGEX 0, 0, 227, 132
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "CEditExample"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
EDITTEXT        IDC_MSG,28,22,174,68,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
PUSHBUTTON      "Start",IDC_START,31,108,52,17
PUSHBUTTON      "Stop",IDC_STOP,135,108,52,17
END


头文件

// CEditExampleDlg.h : header file
//

#pragma once
#include "afxwin.h"

// CCEditExampleDlg dialog
class CCEditExampleDlg : public CDialogEx
{
// Construction
public:
CCEditExampleDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
enum { IDD = IDD_CEDITEXAMPLE_DIALOG };

protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
HICON m_hIcon;

// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedStart();
afx_msg void OnBnClickedStop();
afx_msg void OnTimer(UINT_PTR nIDEvent);

private:
static DWORD WINAPI UpdateMsgProc(LPVOID lpDlg);
void UpdateMsg();

private:
CEdit m_ctrlMsg;
CString m_sMsg;
HANDLE m_hThread;
HANDLE m_hStopEvent;
UINT m_nTimerID;
};


实现文件

// CEditExampleDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CEditExample.h"
#include "CEditExampleDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CCEditExampleDlg::CCEditExampleDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CCEditExampleDlg::IDD, pParent)
, m_sMsg(_T(""))
, m_hThread(NULL)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

m_hStopEvent = ::CreateEventA(NULL, TRUE, FALSE, NULL);
}

void CCEditExampleDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MSG, m_ctrlMsg);
DDX_Text(pDX, IDC_MSG, m_sMsg);
}

BEGIN_MESSAGE_MAP(CCEditExampleDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_START, &CCEditExampleDlg::OnBnClickedStart)
ON_BN_CLICKED(IDC_STOP, &CCEditExampleDlg::OnBnClickedStop)
ON_WM_TIMER()
END_MESSAGE_MAP()

BOOL CCEditExampleDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

// Add "About..." menu item to system menu.

// .... some code was deleted.

// TODO: Add extra initialization here
m_nTimerID = 1;

return TRUE;  // return TRUE  unless you set the focus to a control
}

void CCEditExampleDlg::OnBnClickedStart()
{
::ResetEvent(m_hStopEvent);
SetTimer(m_nTimerID, 1000, NULL);
m_hThread = ::CreateThread(NULL, 0, UpdateMsgProc, this, 0, NULL);
}

DWORD WINAPI CCEditExampleDlg::UpdateMsgProc(LPVOID lpDlg)
{
CCEditExampleDlg *pDlg = (CCEditExampleDlg*)lpDlg;

CString temp;
for (int i = 0; i < 10000; i++) {
temp.Format("Line %d\r\n", i + 1);
pDlg->m_sMsg += temp;

if (WAIT_OBJECT_0 == ::WaitForSingleObject(pDlg->m_hStopEvent, 1000)) {
return 1;
}
}

return 0;
}

void CCEditExampleDlg::UpdateMsg()
{
UpdateData(FALSE);

m_ctrlMsg.LineScroll(m_ctrlMsg.GetLineCount() - 1);
}

void CCEditExampleDlg::OnBnClickedStop()
{
::SetEvent(m_hStopEvent);
switch (::WaitForSingleObject(m_hThread, 10000)) {
case WAIT_OBJECT_0:
m_sMsg += "Thread stopped.\r\n";
break;

case WAIT_TIMEOUT:
m_sMsg += "Thread not stopped, time out.\r\n";
break;

default:
m_sMsg += "Unknown state.\r\n";
break;
}

KillTimer(m_nTimerID);

UpdateMsg();
}

void CCEditExampleDlg::OnTimer(UINT_PTR nIDEvent)
{
assert(nIDEvent == m_nTimerID);

UpdateMsg();

CDialogEx::OnTimer(nIDEvent);
}


补充

如果UpdateMsg()之后,再调用UpdateData(FALSE),那么编辑框会自动显示最开始的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ui