C language realizes the digital rain effect

  • 2020-06-03 07:31:22
  • OfStack

Examples of this paper share the C language to achieve the digital rain effect display specific code for your reference, the specific content is as follows


#include <windows.h>
#include <windowsx.h>

#define ID_TIMER  1
#define STRMAXLEN 25 //1 The maximum length of the columns displayed 
#define STRMINLEN 8 //1 The minimum length of the displayed columns 

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
typedef struct tagCharChain // The whole thing ACTS as a screen 1 A display list , It's a two-way list 
{
    struct tagCharChain *prev; // The first element of a linked list 
    TCHAR ch;         //1 Of the display columns 1 A character 
    struct tagCharChain *next; // The last element of the list 
}CharChain, *pCharChain;

typedef struct tagCharColumn
{
    CharChain *head, *current, *point;
    int x, y, iStrLen; // Displays the beginning of the column x,y coordinates ,iStrLen Is the length of this column 
    int iStopTimes, iMustStopTimes; // The number of times it has stopped and the number of times it has to stop , The number of times you have to stop is random 
}CharColumn, *pCharColumn;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("matrix") ;
    HWND      hwnd ;
    MSG      msg ;
    WNDCLASS  wndclass ;

    wndclass.style        = CS_HREDRAW | CS_VREDRAW ; // class style
    wndclass.lpfnWndProc    = WndProc ;
    wndclass.cbClsExtra    = 0 ;
    wndclass.cbWndExtra    = 0 ;
    wndclass.hInstance    = hInstance ;
    wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ;
    wndclass.hCursor    = LoadCursor (NULL, IDC_ARROW) ;
    wndclass.hbrBackground    = (HBRUSH) GetStockObject (BLACK_BRUSH) ;
    wndclass.lpszMenuName    = NULL ;
    wndclass.lpszClassName    = szAppName ;

    if(!RegisterClass (&wndclass))
    {
      MessageBox (NULL, TEXT (" This program must be run in NT Under the !"), szAppName, MB_ICONERROR) ;
      return 0;
    }

    hwnd = CreateWindow (szAppName, NULL,
              WS_DLGFRAME | WS_THICKFRAME | WS_POPUP, // windows style
              0, 0,
              GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
              NULL, NULL, hInstance,
              NULL) ;

    ShowWindow (hwnd, SW_SHOWMAXIMIZED) ; // Maximized display  show windows
    UpdateWindow (hwnd) ;
    ShowCursor(FALSE); // Hide the mouse cursor 
    
    srand ((int) GetCurrentTime ()) ; // Initialize the random number generator 
    while (GetMessage (&msg, NULL, 0, 0))
    {
      TranslateMessage (&msg) ;
      DispatchMessage (&msg) ;
    }
    ShowCursor(TRUE); // Display mouse cursor 
    return msg.wParam ;
}

TCHAR randomChar() // Random character generation function 
{
    return (TCHAR)(rand()%(126-33)+33); //33 to 126 between 
}

int init(CharColumn *cc, int cyScreen, int x) // Initialize the 
{
    int j;
    cc->iStrLen = rand()%(STRMAXLEN-STRMINLEN) + STRMINLEN; // Displays the length of the column 
    cc->x = x+3 ;    // Displays the beginning of the column x coordinates 
    cc->y =rand()%3?rand()%cyScreen:0; // Displays the beginning of the column y coordinates 
    cc->iMustStopTimes = rand()%6 ;
    cc->iStopTimes  = 0 ;
    cc->head = cc->current =
            (pCharChain)calloc(cc->iStrLen, sizeof(CharChain)); // Generate display columns 
    for(j=0; j<cc->iStrLen-1; j++)
    {
        cc->current->prev = cc->point; //cc->point1 The first element of the display column 
        cc->current->ch = '\0';
        cc->current->next = cc->current+1; //cc->current+11 The last element of a column 
        cc->point     = cc->current++; //cc->point = cc->current; cc->current++;
    }
    cc->current->prev = cc->point; // The last 1 A node 
    cc->current->ch = '\0';
    cc->current->next = cc->head;
    cc->head->prev  = cc->current; // The front of the head node 1 The end of this chain 1 An element 

    cc->current = cc->point = cc->head; //free The requested memory is to be used current When the parameter 
    cc->head->ch = randomChar(); //  On the head of the chain   Element filling 
    return 0;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   HDC   hdc ;
   //ctn  Used to determine the 1 A display chain whether   Move down , If you wait more than you have to wait ,ctn It's going to go down 
   int i, j, temp, ctn; //j for 1 The number of display chains other than the head of the chain displayed on the screen y coordinates ,temp Excessive green to black 
   static HDC hdcMem;
   HFONT  hFont;
   static HBITMAP hBitmap;
   static int cxScreen, cyScreen; // Screen width   highly .
   static int iFontWidth=10, iFontHeight=15, iColumnCount; // Font width   highly ,  The number of columns 
   static CharColumn *ccChain;

   switch (message)
   {
    case WM_CREATE:
      cxScreen = GetSystemMetrics(SM_CXSCREEN) ; // The width of the screen 
      cyScreen = GetSystemMetrics(SM_CYSCREEN) ;
      SetTimer (hwnd, ID_TIMER, 10, NULL) ;

      hdc = GetDC(hwnd);
      hdcMem = CreateCompatibleDC(hdc);
      hBitmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen);
      SelectObject(hdcMem, hBitmap);
      ReleaseDC(hwnd, hdc);
      // Create a font 
      hFont = CreateFont(iFontHeight, iFontWidth-5, 0, 0, FW_BOLD, 0, 0, 0,
                DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                DRAFT_QUALITY, FIXED_PITCH | FF_SWISS, TEXT("Fixedsys"));
      SelectObject(hdcMem, hFont);
      DeleteObject (hFont) ;
      SetBkMode(hdcMem, TRANSPARENT); // Set the background mode to   transparent 
      iColumnCount = cxScreen/(iFontWidth*3/2); // The number of columns of letter rain displayed on the screen 

      ccChain = (pCharColumn)calloc(iColumnCount, sizeof(CharColumn));
      for(i=0; i<iColumnCount; i++)
      {
        init(ccChain+i, cyScreen, (iFontWidth*3/2)*i);
      }
      return 0 ;

    case WM_TIMER:
      hdc = GetDC(hwnd);
      PatBlt (hdcMem, 0, 0, cxScreen, cyScreen, BLACKNESS) ; // Paint the memory device image black 
      for(i=0; i<iColumnCount; i++)
      {
        ctn = (ccChain+i)->iStopTimes++ > (ccChain+i)->iMustStopTimes;
        //
        (ccChain+i)->point = (ccChain+i)->head; //point Used to traverse the entire display column 
        
        // The first 1 Three characters are displayed as   white 
        SetTextColor(hdcMem, RGB(255, 255, 255));
        TextOut(hdcMem, (ccChain+i)->x, (ccChain+i)->y, &((ccChain+i)->point->ch), 1);
        j = (ccChain+i)->y; 
        (ccChain+i)->point = (ccChain+i)->point->next;
        // Traverse the entire display column , Display the characters in the display column from bottom to top 
        temp = 0 ; //temp Excessive green to black 
        while((ccChain+i)->point != (ccChain+i)->head && (ccChain+i)->point->ch)
        {
            SetTextColor(hdcMem, RGB(0, 255-(255*(temp++)/(ccChain+i)->iStrLen), 0));
            TextOut(hdcMem, (ccChain+i)->x, j-=iFontHeight, &((ccChain+i)->point->ch), 1);
            (ccChain+i)->point = (ccChain+i)->point->next;
        }
        if(ctn)
          (ccChain+i)->iStopTimes = 0 ;
        else continue;
        (ccChain+i)->y += iFontHeight; // I'll show it next time y coordinates   For the current y Coordinate with  1 The height of two characters 
        // If it starts to show y Coordinate minus   The length of the entire display column exceeds the height of the screen 
        if( (ccChain+i)->y-(ccChain+i)->iStrLen*iFontHeight > cyScreen)
        {
            free( (ccChain+i)->current );
            init(ccChain+i, cyScreen, (iFontWidth*3/2)*i);
        }
        // The head of the list   The first element of this linked list , Because the next time I start showing it   This is equivalent to adding an element to the beginning of the entire display column , And then it goes up at the beginning 
        (ccChain+i)->head = (ccChain+i)->head->prev;
        (ccChain+i)->head->ch = randomChar();
      }
      
      BitBlt(hdc, 0, 0, cxScreen, cyScreen, hdcMem, 0, 0, SRCCOPY);
      ReleaseDC(hwnd, hdc);
      return 0;

    case WM_RBUTTONDOWN:
      KillTimer (hwnd, ID_TIMER) ;
      return 0;

    case WM_RBUTTONUP:
      SetTimer (hwnd, ID_TIMER, 10, NULL) ;
      return 0;

    // Deal with the aftermath 
    case WM_KEYDOWN:
    case WM_LBUTTONDOWN:
    case WM_DESTROY:
      KillTimer (hwnd, ID_TIMER) ;
      DeleteObject(hBitmap);
      DeleteDC(hdcMem);
      for(i=0; i<iColumnCount; i++)
      {
        free( (ccChain+i)->current );
      }
      free(ccChain);
      PostQuitMessage (0) ;
      return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}

Related articles: