Gribble1

介绍 蛀木水虱n。"呈现为不可读文本的随机二进制数据。数据中的噪声特征 流显示为gribble。比特率不匹配的调制解调器通常会产生gribble(更具体地说,波特率) 呕吐)。将二进制文件转储到屏幕是一个很好的抱怨源,并且(如果铃声/扬声器是活动的) 头痛。”术语词典 多年前,当我第一次开始玩“pooters mumble”时,其中一件“有趣”的事情就是玩 用一些简单的图形例程。通常,在图形方面你做不了很多事情,但那就是 让尝试做一些事情变得更加有趣。 在开始使用Visual C和MFC后不久,有人让我写一个需要的程序 只是为了显示一些图形——仅此而已。实际上,我花了一段时间来弄清楚如何使用CWnd 所有伴随的铃声和哨声-框架,标题栏,等等。但你瞧,这并不难,而且 提供了一个整洁的画布,可以使用任何您想要使用的东西。 如果您正在考虑编写一个“kiosk”类型的程序,我认为我在这里提供的Gribble窗口是有用的 (我)。我还希望Gribble1项目可以成为那些希望进行探索的人的一个有用的学习工具 Windows图形的世界,所以我写这篇文章主要是作为初学者的教程。那就是说,我不太会去 在这篇短文中深入探讨设备上下文和GDI对象的主题——这里的目标只是得到 Gribble窗口启动并运行,并提供一个简单的示例(经典的“Lissajou”图)来启动。 Gribble1项目 Gribble1是一个现成的VC6应用向导生成的基于MFC的EXE项目,不支持文档/视图。与 这样,我就添加了一个名为Gribble的菜单项,在CGribble1App中处理了Go选项。 接下来,我使用类向导创建了一个CGribbleWnd类——选择新类,然后派生CGribbleWnd 来自“通用的CWnd”。(你需要滚动屏幕才能看到这个。)然后我声明了一个CGribbleWnd的实例 在App类中,并叫它m_wndGribble。 现在,CWnd在创建之前都不是窗口,在这里您有机会定义一些非常基本的内容 属性。这是我们在CGribbleWnd本身之外唯一需要的代码,如果你需要的话,你会使用它 在您自己的项目中合并CGribbleWnd。在我的例子中,Gribble窗口在CGribble1App::OnGribbleGo()中创建。 使用它自己的窗口类和WS_VISIBLE|WS_POPUP的最小属性集。这是最小的 属性设置,去掉那些讨厌的边框和东西。 我们在这里要做的就是注册窗口类并调用m_wndgribb . createex()—内置的 CWnd方法: 隐藏,复制Code

void CGribble1App::OnGribbleGo() 
{
    // Let's create the Gribble window!
    if(!m_wndGribble.m_hWnd) {
        
        CString csWndClass = AfxRegisterWndClass(CS_OWNDC, 0, 0, 0);
        
        if(!(m_wndGribble.CreateEx(WS_EX_LEFT,
            (LPCTSTR)csWndClass,
            "Gribble Window",
            WS_VISIBLE|WS_POPUP,
            0,0,0,0, NULL, NULL ))) 
        {
            AfxMessageBox("Failed to Create Gribble Window)");
            return;
        }
    }
}

我们的Gribble窗口应该能够从那里获取它,这是在它的OnCreate方法中做到的: 隐藏,收缩,复制Code

int CGribbleWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
 
    // load nifty cursor
    m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR2);
 
    // we'll want to do this in OnActivate too
    SetCursor(m_hCursor);
    ShowCursor(true);
 
    // since this window has its own DC we can stash it away... 
    m_pDC = GetDC();
 
    // get some screen stats...
    m_pixelsX = m_pDC->GetDeviceCaps(HORZRES);
    m_pixelsY = m_pDC->GetDeviceCaps(VERTRES);
    m_bitsPixel = m_pDC->GetDeviceCaps(BITSPIXEL);
     
    TRACE("Screen is %d by %d
", m_pixelsX, m_pixelsY);
    TRACE("Color depth is %d bits per pixel
", m_bitsPixel);
 
    // full screen - in whatever color OnEraseBkgnd is using...
    MoveWindow(0,0,m_pixelsX, m_pixelsY);
 
    return 0;
}

这里,我们做一些准备。首先,我们需要设备上下文,这样我们就能知道屏幕的大小 是多少。我们可以用GetDeviceCaps()请求更多的信息,但现在我们真正需要的是 所关心的是x和y的最大值。(获取颜色深度的调用是从原始得到的 类,它需要检查设置对于它正在使用的位图是否足够高。) 接下来的管理工作是通过调用MoveWindow()将窗口大小调整为屏幕大小。 (注意,当我们调用CreateEx()时,我们为顶部、左侧、宽度和高度指定了0,因此我们需要 这样做。) MoveWindow()方法有第五个参数bRepaint,默认值为TRUE和 开始滚动我们的球-告诉操作系统,我们想要排队一些绘画消息。哪一个 反过来,结果是我们得到一些绘画信息。 到目前为止一切都很好——但是我们的泛型CWnd派生类需要处理这些绘制消息,特别是WM_ERASEBKGND WM_PAINT,因为基类(CWnd)没有为我们做任何事。类向导的救援 再次—选择CGribbleWnd,突出显示WM_ERASEBKGND条目并选择Add Function,然后 编辑代码。我的CGribbleWnd::OnEraseBkgnd()是这样的: 隐藏,复制Code

BOOL CGribbleWnd::OnEraseBkgnd(CDC* pDC) 
{
    // we'll configure this later...
    m_backColor = RGB(0,0,0);
 
    CBrush cb(m_backColor);
    HBRUSH hOldBrush = (HBRUSH)pDC->SelectObject(cb);

    RECT rect = {0,0,m_pixelsX,m_pixelsY};
    pDC->FillRect(&rect,&cb);

    pDC->SelectObject(hOldBrush);
    cb.DeleteObject();

    return TRUE;
}

这里我们创建了一个笔刷,一种特殊类型的GDI对象,并使用它使屏幕变黑。这就 我们有一个大黑屏。 注意这里有一个非常重要的代码三明治,如果您的程序要成为a,您必须遵守它 良好的Windows公民,即当一个GDI对象被选择到一个关联设备时,旧的对象必须是 保存和恢复。这允许设备上下文在完成时正确地返回资源,并保存您 资源泄露这一可怕的罪恶。当我们谈到这个问题时,还有两点- 1。创建窗口类 正如我上面提到的,拥有自己的关联设备也被认为是一个禁忌。我这样做是为了(希望)保存 时间,在调用GetDC的上下文中。2. 上面的代码三明治可以用c替换呼叫SaveDC () 和RestoreDC(),可以方便的很多对象时被选中的设备上下文。 接下来,使用类向导创建OnPaint()方法中,我们得到了一个不错的小练习 我们的windows图形。我看起来像这样: 隐藏,收缩,复制Code

void CGribbleWnd::OnPaint() 
{
    CPaintDC dc(this); // device context for painting
    
    /**
       Now do some drawing... how bout a Lissajou figure...
       {  Asin(wt + B) }
    **/
 
    // normally we'd do this kind of initialization in OnCreate or the constructor,
    // but I want to localize things here, so we can treat OnPaint as a mini program!
 
    // start with a classic seed for the Lissajou... one time init...
    static int s_nLisXCoef = 1;
    static int s_nLisYCoef = 3;
    static int s_nLisYOffset = 44;
 
    ++s_nLisXCoef;
    ++s_nLisYCoef;
    
    int x,y;
    for (float t = 0; t < 32767; t+=.2) 
    {
        x = sin(s_nLisXCoef*t) * m_pixelsX/2 + m_pixelsX/2;
        y = sin(s_nLisYCoef*t+s_nLisYOffset) * m_pixelsY/2 + m_pixelsY/2;
 
        dc.SetPixel(x, y, RGB(255,80,255));
    }

    // Do not call CWnd::OnPaint() for painting messages
} 

有代码CGribbleWnd: OnLButtonDown()调用()开始失效 整个绘画过程,导致一个新的图被显示在响应鼠标单击。的 代码32767电话设置像素,所以它不会很快回应你的鼠标点击,但是 不太坏又是;随着数据越来越复杂,其整洁看他们填写。 可能唯一的另一件事是漂亮的游标。有两个游标中定义的资源 编辑器和OnCreate加载,并使用第二个,一种StarCraft-like箭头。保持这 光标需要处理最后一个消息: 隐藏,复制Code

void CGribbleWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
{
    CWnd::OnActivate(nState, pWndOther, bMinimized);
    
    if(nState != WA_INACTIVE ) 
    {
        SetCursor(m_hCursor);
        ShowCursor(true);
    }
}

最后一个添加处理程序没有提到OnKeyDown,用于出口通过DestroyWindow () 当escape键被按下。 总结 现在你明白了吧,一个标准的CWnd有六个消息处理程序添加(其中一些很简单)和你 祝你有美好的全屏窗口图形。颜色你可以玩,在离开之前 Lissajou主题开始你可能想尝试不同的系数等。这里唯一的图形叫SetPixel (), 它不需要任何的GDI对象或SelectObject()调用,所以你可以安全地玩耍,没有 消耗资源的恐惧。 Lissajou数据是一个典型的“简单”图形的东西。也许一些数学上的 介意我们中间有其他一些很酷的公式来分享。那太好了,我试图使OnPaint () 或多或少独立使用本地静态var 类成员,如果你坚持这个会议你可以提交有趣的新蛀木水虱概念 通过粘贴OnPaint()代码到一个消息并发布它。也许有人能够发现 蛀木水虱应该是什么样子。 蛀木水虱快乐 本文转载于:http://www.diyabc.com/frontweb/news5222.html

原文地址:https://www.cnblogs.com/Dincat/p/13462450.html